Java 锁升级(锁膨胀)、锁降级

锁升级:偏向锁、轻量级锁、重量级锁的过渡。

https://blog.csdn.net/haoranhaoshi/article/details/92388612

优先尝试低级锁,不能适用,就升级锁。线程获取到不被其他线程获取的监视类或对象,监视类或对象头部记录线程ID,线程退出对监视类或对象的获取时直接退出,是偏向锁。如果有其他线程来获取监视类或对象,发现头部记录的线程ID不是自己的ID(https://blog.csdn.net/haoranhaoshi/article/details/108501633),就升级为轻量级锁。轻量级锁采用CAS机制(https://blog.csdn.net/haoranhaoshi/article/details/108507092),尝试一定次数(默认10)获取不到监视类或对象,则升级为重量级锁(一旦获取不到监视类或对象就阻塞(https://blog.csdn.net/haoranhaoshi/article/details/108461058))。

因为操作唤醒阻塞的线程需从用户态切换到内存态,开销大,所以才优先使用轻量级锁进行循环判断是否可获取监视类或对象。

锁降级:写锁降级成为读锁。持有写锁的同时,获取到读锁,然后释放写锁。避免读到被其他线程修改的数据。

oracle官网锁降级示例:

 class CachedData {
   Object data;
   volatile boolean cacheValid;
   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

   void processCachedData() {
     rwl.readLock().lock();
     // 缓存无效
     if (!cacheValid) {
        // Must release read lock before acquiring write lock
        // 释放读锁
        rwl.readLock().unlock();
        // 尝试获取写锁
        rwl.writeLock().lock();
        try {
          // Recheck state because another thread might have
          // acquired write lock and changed state before we did.
          // 再次判断获取是否无效
          if (!cacheValid) {
              // 获取数据
            data = ...
            cacheValid = true;
          }
          // Downgrade by acquiring read lock before releasing write lock
          // 锁降级
          rwl.readLock().lock();
        } finally {
          rwl.writeLock().unlock(); // Unlock write, still hold read
        }
     }
     // 经过很长的时间做一些处理、而且不想我刚刚自己更新的数据被别人改了
     try {
       use(data);
     } finally {
       rwl.readLock().unlock();
     }
   }
 }

猜你喜欢

转载自blog.csdn.net/haoranhaoshi/article/details/108509688