java 多线程-synchronized (一)

 

1:锁升级到的过程

  首先要了解2个概念

  1. 什么是cas
  2. 对象在内存中的布局

1.1:CAS(compare and swap):自旋锁

 

 

 

     这个过程中存在ABA问题:

  1. 进程P1在共享变量中读到值为A
  2. P1被抢占了,进程P2执行
  3. P2把共享变量里的值从A改成了B,再改回到A,此时被P1抢占。
  4. P1回来看到共享变量里的值没有被改变,于是继续执行。但实际过程中A数据已经被P2线程修改过,
    1. 虽然共享变量没改变,但是实际过程中是有修改动作 我们没法知道数据的修改历史

解决方案: 添加版本或者时间戳

 

 

1.2:java 对象+在内存中的布局

普通对象在内存中分为4块内容

  1. markword  标记位
  2. 类型指针 class pinter  哪个类,如果是student类这个就是student.class
  3. 实例数据,对象里面的成员变量
  4. 对齐位  前面字节不能被8整除,补齐,jvm  以安块来读取的

 

 例如以下代码

Object o = new Object();
String s = ClassLayout.parseInstance(o).toPrintable();

 

 

 

 

  1.   图(1)  8个字节就是是markword
  2.   图(2)    4就是class pinter 
  3.  补齐位,前面12个字节,后面补齐4位

 

 

 

知道对象布局后,我们再看是怎么上锁

//无锁

Object o = new Object();
String s = ClassLayout.parseInstance(o).toPrintable();
System.out.print(s);
//给对象上锁,就是对象头markword发生变化,
synchronized (o){
System.out.print(ClassLayout.parseInstance(o).toPrintable());
 
 

 

 

 

 

 通过图片里面数据对比,所谓的加锁, 就是修改对象的头部  就是markword 的状态,我们观察对象的锁的升级过程,就是看markword的变化

 

上图红色划线的地方就是锁标志位(根据下午,我们可以根据markword 的参数值,来了解当前对象现在是否上锁)

 

 锁的状态分为  无锁,偏向锁,轻量级锁,重量级锁

 

1.3锁的升级过程

 

 

 

刚实例对象的时候,我们有

 

打个比方

 

 假设只有一台电脑,

  1: 张三要用,只有张三一个人是的时候,直接在门上写着张三在使用,记录下id(线程id 记录到markword 里面)

   2:现在李四也要使用这台电脑,现在就要开始竞争了,谁能够把自己信息贴到这个门上(),谁就能用这把锁(轻量锁)

 

   3:如果人特别多,1000个人竞争,只有1个人在使用,还有99个在自旋,这个适合就需要惊动管理员(操作系统),来维护次序, 这个时候就需要升级到重量级锁(提供队列,wait set)

 

 

注升级重量级锁:

jdk1.6之前

某个线程自旋次数超过10次

等待自旋线程超过cpu 核素1/2  比如cpu 8核,5个线程就升级

 

jdk1.6以后 根据线程情况,判断是否需要升级(自适应自旋)

 

 

 参考地址: https://www.cnblogs.com/cxiaocai/p/12189848.html

 

posted @ 2020-05-08 22:32  wayne.su  阅读(180)  评论(0)    收藏  举报