当前位置: 首页 > news >正文

synchronized的实现原理与应用

文章目录

  • 一、对象头
  • 二、锁的升级和对比
    • 1.偏向锁
    • 2.轻量级锁


写一个关于卖票的方法 - - 多线程操纵数据

public class TestSync {
public static void main(String[] args) throws InterruptedException {
        MaiPiao piao = new MaiPiao();
        Thread [] threads = new Thread[10];//10个窗口
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new Window(piao));
        }//对线程进行循环 , 把买的票传给他
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }//让线程去启动
        Thread.sleep(5000); //让主线程休5s 让那10个线程跑完
        piao.tikectCheck(); //检查一下还有没有票
    }
}
//窗口负责卖票
class Window implements Runnable{
    //我持有一个票
    private MaiPiao piao;
    public Window(MaiPiao piao) {
        this.piao = piao;
    }
    @Override
    public void run() {
        for (int i = 2; i < 100; i++) {
            piao.sold();
        }
    }
}
class MaiPiao{
    private int tikect=1000;
    public void sold(){
        tikect--;
    }
    public void tikectCheck(){
        System.out.println(tikect);
    }

}

预期结果是20 , ,但是有些运行结果并不是20,这是一个不安全的线程
如果在 public void sold(){ }中加一个synchronized ,private int tikect=1000;的数值变大一点, 输出结果还是20
synchronize是一个重量级锁
先来看下利用synchronized实现同步的基础:Java中的每一个对象都可以作为锁。具体表现 为以下3种形式:
①对于普通同步方法,锁是当前实例对象。
②对于静态同步方法,锁是当前类的Class对象。
③对于同步方法块,锁是Synchonized括号里配置的对象。
②的使用
在这里插入图片描述
在这里插入图片描述
改成静态的,相互之间是共享的 ;;; 输出结果是20
10个线程每个都持有一个票这个对象,对象只供自己的锁使用,又回到了开始的状态
③ 的使用
在这里插入图片描述

一、对象头

synchronized用的锁是存在Java对象头里的。如果对象是数组类型,则虚拟机用3个字宽 (Word)存储对象头,如果对象是非数组类型,则用2字宽存储对象头。在32位虚拟机中,1字宽 等于4字节,即32bit,在64位虚拟机中,1字宽就是8位.64bit

二、锁的升级和对比

竞争: 十个锁抢一个线程就是竞争
锁只能升级不能降级

1.偏向锁

当一个线程访问同步代码块并且获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的id
在对象上刻上自己的id,下次在访问的时候直接去比较就行了
在这里插入图片描述
等到竞争才会释放锁的机制

2.轻量级锁

CAS操作,比较并交换,比较成功交换,不成功不交换,…
轻量级解锁时,会使用原子的CAS操作将Displaced Mark Word替换回到对象头,如果成 功,则表示没有竞争发生。如果失败,表示当前锁存在竞争,锁就会膨胀成重量级锁。图2-2是 两个线程同时争夺锁,导致锁膨胀的流程图。
在这里插入图片描述
虽然在竞争,由于持有的时间不是很长,线程2有所谓的耐心,在耐心耗完之前获得了锁,便不会膨胀成轻量级锁

相关文章:

  • 网上商城之支付
  • 一次搞懂Java如何调用Kotlin的高级特性
  • MyBatis各种SQL操作及执行添加功能获取自增的主键
  • 【学习笔记】模拟赛题解
  • node.js 使用教程-3.gulp-file-include 详细教程
  • 【可视化大屏教程】用Python开发智慧城市数据分析大屏
  • 【云原生 | 从零开始学Kubernetes】二十三、Kubernetes控制器Statefulset
  • git三板斧--Linux
  • 内存分配.
  • 谷粒商城超详细笔记+踩坑(2)——分布式组件、前端基础(回顾知识点)
  • 为 TiDB 客户端服务端间通信开启加密传输
  • C语言函数解决问题:1.求二进制中不同位的个数;2.交换二进制的奇数位和偶数位;3.使用指针打印数组内容
  • PyQT5入门案例(一)工资统计系统
  • Life:歌曲学习之教一个不会唱歌的人学会唱出《情非得已》、《海阔天空》、《红日》、《老男孩》等歌曲
  • 24.STM32的IO口扩展PCF8574
  • 【Leetcode】101. 对称二叉树
  • 4个实用的微服务测试策略
  • Angular2开发踩坑系列-生产环境编译
  • extract-text-webpack-plugin用法
  • Idea+maven+scala构建包并在spark on yarn 运行
  • node和express搭建代理服务器(源码)
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 笨办法学C 练习34:动态数组
  • 聚类分析——Kmeans
  • 每天一个设计模式之命令模式
  • 前端设计模式
  • 微信小程序:实现悬浮返回和分享按钮
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 用element的upload组件实现多图片上传和压缩
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • # Maven错误Error executing Maven
  • #etcd#安装时出错
  • #pragma once
  • #前后端分离# 头条发布系统
  • (1) caustics\
  • (Oracle)SQL优化技巧(一):分页查询
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (二十三)Flask之高频面试点
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (转)使用VMware vSphere标准交换机设置网络连接
  • (转)为C# Windows服务添加安装程序
  • ******之网络***——物理***
  • **CI中自动类加载的用法总结
  • .apk文件,IIS不支持下载解决
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .NET gRPC 和RESTful简单对比
  • .NET 设计模式初探
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .Net的C#语言取月份数值对应的MonthName值
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境