保证线程同步的方法(线程通信的方法),wait/notify ,synchronized,Reentranklock,,
我所认为的认为的synchronized,锁的膨胀过程,这是一个怎样的概念:无锁状态>偏向锁>轻量级锁>重量级锁;
首先来说说为什么是这样设定(我所认为的),首先来说说对象头吧,其实我只知道冰山一角,我导入一个jar包,jol-core-0.8.jar,这个jar包可以去查看我们的对象头,今天以64位计算机来说,我们先创建一个最简单的对象,

public class L {private String name;
}

对,没错,什么东西都没有,来看看创建一个L的对象的对象头是什么样子

   L l=new L();
//   l.hashCode();//  System.out.println(ClassLayout.parseClass(L.class).toPrintable());System.out.println(ClassLayout.parseInstance(L.class).toPrintable());
OFFSET  SIZE                                              TYPE DESCRIPTION                               VALUE0     4                                                   (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)4     4                                                   (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)8     4                                                   (object header)                           df 03 00 20 (11011111 00000011 00000000 00100000) (536871903)

这里只是截取了对象头,采用小端,可以看出,在64为操作系统,一个对象对象头为96bit,(对象头由俩个词组成,Mark Word,Klass Pointer(类的元数据地址,方法区的类的模板信息))
其中Mark Word为64bit,Klass Pointer为32bit
都知道一个对象由对象头+实例数据+填充数据,构成,对象头主要有一个对象的锁状态,hash值,分代年龄等构成
一个对象锁状态,也是在对象头中有2个bit所保存(还有GC标记也有一位),一共是三位所保存;
在jdk1.6之前synchronized是一把重量级锁,(它只要有线程竞争就会有cup的用户态和内核态之间的转变),所以才出现了一个ReentrankLock的锁,而这个锁性能在jdk1.6之前是要比sychronized的性能好很多的,ReentrankLock详解在后续文章中;在jdk1.6之后,oracle将synchronized优化,也就是我们所说的锁的膨胀过程;我们一个状态一个状态的说:

偏向锁:适用于线程少或者线程不竞争(交替执行,一个完了,下一个才来),当一个线程经过同步代码块或同步方法时,会去加锁(假设目前无锁状态),那么如何加呢?首先没有被加锁时,这个对象或者类对象的对象头标记为无锁状态,当第一个线程,线程1来时,可以直接加锁,那么这个对象的对象头就变为偏向锁状态;即这个线程的线程id会被记录在被锁住对象的对象头中,这就是一个偏向线程1的偏向锁,即使这个线程执行完,退出了同步方法,仍然不会去释放锁(所以锁的膨胀过程时不可逆的),这个锁仍然是偏向这个线程的偏向锁,而这个线程下次在进入这个同步方法时,只需要判断当前对象的对象头的线程id与当前线程的线程id相同否,相同则直接进入,不同则判断对象头中保存的线程id对应的线程是否执行完毕(是否已经退出同步),如果执行完毕,则将对象头中的线程id改为当前线程的线程id,当前线程进入(
同样,执行完后也不会释放锁),如果上一个线程还没有执行完,则此时就是竞争的状态而非交替了,锁膨胀为轻量级锁;
那么为什么引入偏向锁呢?
同一个线程只需加锁一次,可以重复进出,不需要花费大量时间去加锁,解锁,同时这个被加锁的线程“被偏向了”,即这个线程进出快

轻量级锁:
上述说到,如果有线程竞争时,锁膨胀为轻量级锁,同样我们先来说说这个加锁过程又是怎么样的,轻量级锁,即这个被锁住的对象的对象头的俩位bit改变,(01.10.11.00)此时为轻量级锁,当第二个线程来竞争时,如果线程1执行完了,则线程2进入,加锁:虚拟机首先在这个线程的栈帧中创建一个名为锁记录(lock Record)的空间,用于储存当前线程的Mark Word 的拷贝Displaced Mark Word,也就是说相当于将对象头中的hash值,分代年龄,锁状态等拷贝一份,然后虚拟机将使用cas操作去将对象头中的Mark Word 更新为一个指向Displaced Mark Word的指针,再将Displaced Mark Word中的锁状态改为轻量级锁,如图:
如果线程1还在同步快中,线程2也不会阻塞,由轻量级锁的缘故,线程2会去进行一定次数的自旋,为什么是自旋呢?还是一个道理,让其阻塞会涉及内核的转变,会十分消耗性能,在线程竞争不激烈时(即少量线程在竞争时),让等待进入的少量线程去自旋要比让其去阻塞的性能要好很多,因为自旋相当于就是让这些等待的线程去尝试获取锁(即循环获取锁,知道成功为止),在只有少量线程竞争时,自旋好一些。当线程很多在竞争时,就膨胀为重量级锁

重量级锁:就是jdk1.6之前的锁,让所有等待的线程全部去阻塞,也就是让他们由操作系统做线程上下文的切换,由用户态转变为内核态,性能很低,但为了保证同步,只有这样,因为当很多线程竞争时,大量线程自旋会耗费大量cpu,所以让其阻塞吧

synchronized是一把非公平锁,即所有等待全部去竞争锁,没有先后之分,上述所说线程加锁,对象加锁,其实是一个概念,我们都知道一句话:被锁住的是对象,所以我们针对的是同一个对象的不同线程来加锁(如果是不同对象,就没有同步可言了);

以上所述,为笔者学习笔记,仅作参考

synchronized加锁过程相关推荐

  1. 偏向锁、轻量级锁、重量级锁加锁过程即锁升级膨胀过程

    偏向锁.轻量级锁.重量级锁加锁过程即锁升级膨胀过程 synchronized 偏向锁 为什么要引入偏向锁 偏向锁加锁过程 线程获取到锁对象的偏向锁之后,执行完同步代码块之后,会释放这个偏向锁吗 使用了 ...

  2. Mysql加锁过程详解(3)-关于mysql 幻读理解

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  3. Mysql加锁过程详解(2)-关于mysql 幻读理解

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  4. Java多线程中使用ReentrantLock、synchronized加锁 简单举例

    Java多线程中使用ReentrantLock.synchronized加锁 简单举例 public class Demo {final static Lock lock = new Reentran ...

  5. java对象头_我的并发编程(二):java对象头以及synchronized升级过程

    一.概述 研究java对象头的目的是详细分析Java的synchronized锁的升级过程,因为synchronized在锁升级的时候,就是依赖对象头的信息来决定的.本博文针对64位的操作系统来对Ja ...

  6. synchronized 加锁 this 和 class 的区别!

    作者 | 王磊 来源 | Java中文社群(ID:javacn666) 转载请联系授权(微信ID:GG_Stone) synchronized 是 Java 语言中处理并发问题的一种常用手段,它也被我 ...

  7. ReadWriteLock读写锁加锁过程

    读写锁案例 + 小小总结 //读这篇文章的时候,建议先看一下,我并发专题中的 Lock.lock() 加锁的过程的文章 //我在写读写锁的时候,好多东西,好多理念都在lock()中体现 // 读读串行 ...

  8. java 静态方法枷锁_Java synchronized静态方法使用synchronized加锁

    昆明达内Java培训的老师上一期讲了Java synchronized实例方法使用synchronized加锁,这一期给同学们讲Java synchronized静态方法使用synchronized加 ...

  9. java synchronized加锁 或者redis锁不起作用

    前几天在代码中需要加锁 使用了synchronized 以及redis锁均一直不起作用 , 寻找几天后发现是因为在Controller层加了@Transactional(rollbackFor = E ...

  10. 【169期】面试官:同学,分析一下MySQL/InnoDB的加锁过程吧

    程序员的成长之路 互联网/程序员/技术/资料共享 关注 阅读本文大概需要 17 分钟. 来自:cnblogs.com/crazylqy/p/7611069.html Hello,大家好,我是良月柒. ...

最新文章

  1. Android’s PreferenceActivity for all API versions
  2. chmod 755 是李鬼(转)
  3. Oracle八大性能视图之v$sort_usage_temp
  4. POJ 3259 Wormholes【最短路/SPFA判断负环模板】
  5. 额!Java中用户线程和守护线程区别这么大?
  6. docker tomcat启动无法进入欢迎页面
  7. fun-函数的数据类型小结
  8. 苹果x来电闪光灯怎么设置_苹果6splus来电没有声音,苹果6sp听筒没有声音怎么回事...
  9. 如何去学习linux
  10. vlang: 新语言尝试,初生牛犊,未来可期
  11. STM32电机库5.4开源注释 KEIL工程文件 辅助理解S STM32电机库5.4开源注释
  12. 在Ubuntu中安装Python科学计算环境
  13. 三十三、Fluent边界条件湍流参数设置详解
  14. 下载youtube 字幕
  15. 天猫总裁靖捷详解新零售:传统商圈平均增长超50%
  16. C语言 | 文件打开关闭
  17. Android studio百度地图SDK开发 2020最新超详细的Android 百度地图开发讲解(3) 路线规划步行骑行驾车路线规划
  18. 常微分方程-变量分离、变量变换、线性微分方程和常数变易法
  19. uniapp中字体加粗问题
  20. 遗传算法:交叉操作 Position-based Crossover (PBX)

热门文章

  1. 记一次hive 报错NoViableAltException(-1@[215:51: ( KW_AS )?])
  2. 在设计软件测试用例的原则,设计软件测试用例需要遵循的四条原则
  3. 软件开发中如何评估工作量
  4. Geos库学习之(一)——Geos库介绍和编译
  5. 通信协议(一)——UART协议
  6. 未能成功加载扩展程序_JVM类加载 - 大碗炸酱面
  7. 复杂美科技有限公司区块链专利
  8. 我的移动开发春季历程,大厂面试题汇总
  9. Helix QAC软件下载安装使用试用
  10. PSO最佳适应度收敛曲线