Synchronized锁升级

Java Synchronized 重量级锁原理深入剖析上(互斥篇)

为什么映入Monitor

处在重量级锁状态时说明有线程没拿到锁需要阻塞等待锁,当拥有锁的线程释放锁后唤醒它继续竞争锁。此处就引入了一个问题:其它线程如何找到被阻塞的线程?我们很容易想到:把阻塞的线程放到多线程共享的(能访问)的列表里。
Synchronized锁升级_第1张图片

mark word

Synchronized锁升级_第2张图片

偏向锁

Synchronized锁升级_第3张图片

轻量级锁Synchronized锁升级_第4张图片Synchronized锁升级_第5张图片

锁重入

// 如果CAS替换不成功,代表锁对象不是无锁状态,这时候判断下是不是锁重入
        // Is it simple recursive case?
        if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) {
          entry->lock()->set_displaced_header(NULL);
        } else {
          // CAS操作失败则调用monitorenter
          CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception);
        }

Synchronized锁升级_第6张图片

偏向锁到轻量锁

线程1当前拥有偏向锁对象,线程2是需要竞争到偏向锁。

  • 1.线程2来竞争锁对象;
  • 2.判断当前对象头是否是偏向锁;
  • 3.判断拥有偏向锁的线程1是否还存在;
  • 4-1.线程1不存在,直接设置偏向锁标识为0(线程1执行完毕后,不会主动去释放偏向锁);
  • 5-1.使用cas替换偏向锁线程ID为线程2,锁不升级,仍为偏向锁;
  • 4-2.线程1仍然存在,暂停线程1;
  • 5.2.设置锁标志位为00(变为轻量级锁),偏向锁为0;
  • 6-2.从线程1的空闲monitor record中读取一条,放至线程1的当前monitor record中;
  • 7-2.更新mark word,将mark word指向线程1中monitor record的指针;
  • 8-2.继续执行线程1的代码;
  • 9-2.线程2自旋来获取锁对象;
    Synchronized锁升级_第7张图片

轻量级到重量级锁

当获取锁冲突多,时间越长的时候,线程肯定无法继续在这里死等了,所以只好先挂起,然后等前面获取锁的线程释放了锁之后,再开启下一轮的锁竞争,而这种形式就是我们的重量级锁。
Synchronized锁升级_第8张图片
Synchronized锁升级_第9张图片

你可能感兴趣的:(java)