java.util.concurrent.locks包

在java.util.concurrent.locks包中有很多Lock的实现类,常用的有ReentrantLock、ReentrantReadWriteLock,其实现都依赖java.util.concurrent.AbstractQueuedSynchronizer类,实现思路都大同小异。

同时,Lock提供了Condition接口,类似与Object的wait/notify,但比后者要方便的多、灵活的多。

ReentrantLock的调用过程

ReentrantLock把所有Lock接口的操作都委派到一个Sync类上,该类继承了AbstractQueuedSynchronizer。

static abstract class Sync extends AbstractQueuedSynchronizer

Sync又有两个子类:

final static class NonfairSync extends Sync
final static class FairSync extends Sync

Reentrant.lock()方法的调用过程(默认非公平锁):

图片描述

AbstractQueuedSynchronizer通过构造一个基于阻塞的CLH队列容纳所有的阻塞线程,而对该队列的操作均通过Lock-Free(CAS)操作,但对已经获得锁的线程而言,ReentrantLock实现了偏向锁的功能。

非公平锁的代码中总是优先尝试当前是否有线程持有锁,一旦没有任何线程持有锁,那么非公平锁就霸道的尝试将锁“占为己有”。如果在抢占锁的时候失败就和公平锁一样老老实实的去请求。也即是说公平锁和非公平锁只是在入AQS的CLH队列之前有所差别,一旦进入了队列,所有线程都是按照队列中先来后到的顺序请求锁。

Lock类调用LockSupport,LockSupport进而调用Unsafe类让操作系统进行park和unpack,从而达到线程的阻塞和恢复。

ReentrantReadWriteLock类

适用于有很多线程都从某个数据结构中读取数据而很少有线程对其进行修改的场景,允许读取器线程共享访问,但与写入器线程依然是互斥的。

private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();  
private Lock readLock = rwl.readLock(); //得到一个可被多个读操作共用的读锁,但它会排斥所有写操作  
private Lock writeLock = rwl.writeLock(); //得到一个写锁,它会排斥所有其他的读操作和写操作

public double getTotalBalance(){  
    readLock.lock();  
    try {
        ...
    } finally {
        readLock.unlock();
    }  
}

public void transfer(){  
    writeLock.lock();  
    try {
        ...
    } finally {
        writeLock.unlock();
    }  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值