java多线程随手记——ReentrantLock的公平锁与非公平锁
2012-09-26 16:37
369 查看
ReentrantLock是concurrent包中,实现的一个锁,下面,我们将对其源码进行分析,以期获得更为有价值的内容。
我们可以按照ReentrantLock的使用方式,来慢慢解析其源码构成。
正如上一章Java多线程随手记——各种锁中的CODE使用的方式,首先我们需要初始化ReentrantLock对象。
从这里可以看到,ReentrantLock实现了公平锁和非公平锁两种方式,首先,我们先把两种实现的思路描述下,然后再看具体实现。
公平锁:看名字就特别和谐,大家都一起排队WC,队伍中轮到谁了谁就去。
非公平锁:这就是特别暴力了,大家都憋不住,队伍排是排,但是只要厕所里的人一出来,不管队伍顺序,靠拳头说话,谁抢到了算谁的。
接下来,我们开始着手具体实现。
公平锁:
首先,看看state是否为0,也就是占用线程已经全部unlock掉,那么再看看自己是不是处于队列的第一个,compareAndSetState()同时检查占用状态,并且修改state值(这是一个底层的CAS原子操作,我是把它理解为类似操作系统中的P操作)。current == getExclusiveOwnerThread()后面便是完成了可重入锁的功效了,当前线程进入lock再这之上再加锁+acquires,之后的章节会详细介绍可重入锁的用途。
非公平锁:
这个非公平锁就野蛮的很,只要看到C为0了,就开抢,不管自己队列顺序,直接做CAS操作,谁先抢到谁就把state这门给关了,让别人进不来。
下面,我们回头看看调用tryAcquire 的acquire方法
可以看到不管公平锁还是非公平锁,都是如果无法获取到当前锁,那么将进入队列中,同时如果满足阻塞条件,那么该线程将会被interrupt掉,直到等待被唤醒。
AbstractQueuedSynchronized 这个类的实现还是挺复杂的,同时它为了该Queue可以并发使用了一个双重检测的设计,打算新开个章节来详细叙述。
下一章节:AbstractQueuedSynchronized类源码分析
我们可以按照ReentrantLock的使用方式,来慢慢解析其源码构成。
正如上一章Java多线程随手记——各种锁中的CODE使用的方式,首先我们需要初始化ReentrantLock对象。
/** * Creates an instance of {@code ReentrantLock}. * This is equivalent to using {@code ReentrantLock(false)}. */ public ReentrantLock() { sync = new NonfairSync(); } /** * Creates an instance of {@code ReentrantLock} with the * given fairness policy. * * @param fair {@code true} if this lock should use a fair ordering policy */ public ReentrantLock(boolean fair) { sync = (fair)? new FairSync() : new NonfairSync(); }
从这里可以看到,ReentrantLock实现了公平锁和非公平锁两种方式,首先,我们先把两种实现的思路描述下,然后再看具体实现。
公平锁:看名字就特别和谐,大家都一起排队WC,队伍中轮到谁了谁就去。
非公平锁:这就是特别暴力了,大家都憋不住,队伍排是排,但是只要厕所里的人一出来,不管队伍顺序,靠拳头说话,谁抢到了算谁的。
接下来,我们开始着手具体实现。
公平锁:
/** * Fair version of tryAcquire. Don't grant access unless * recursive call or no waiters or is first. */ protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (isFirst(current) && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
首先,看看state是否为0,也就是占用线程已经全部unlock掉,那么再看看自己是不是处于队列的第一个,compareAndSetState()同时检查占用状态,并且修改state值(这是一个底层的CAS原子操作,我是把它理解为类似操作系统中的P操作)。current == getExclusiveOwnerThread()后面便是完成了可重入锁的功效了,当前线程进入lock再这之上再加锁+acquires,之后的章节会详细介绍可重入锁的用途。
非公平锁:
final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
这个非公平锁就野蛮的很,只要看到C为0了,就开抢,不管自己队列顺序,直接做CAS操作,谁先抢到谁就把state这门给关了,让别人进不来。
下面,我们回头看看调用tryAcquire 的acquire方法
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
可以看到不管公平锁还是非公平锁,都是如果无法获取到当前锁,那么将进入队列中,同时如果满足阻塞条件,那么该线程将会被interrupt掉,直到等待被唤醒。
AbstractQueuedSynchronized 这个类的实现还是挺复杂的,同时它为了该Queue可以并发使用了一个双重检测的设计,打算新开个章节来详细叙述。
下一章节:AbstractQueuedSynchronized类源码分析
相关文章推荐
- Java多线程之Lock的使用--重入锁(ReentrantLock)、Condition、公平锁和非公平锁、ReentrantReadWriteLock的使用(读写锁)
- java多线程20 : ReentrantLock中的方法 ,公平锁和非公平锁
- ReentrantLock的公平锁与非公平锁浅析
- AbstractQueuedSynchronizer(九)——ReentrantLock公平和非公平锁
- ReentrantLock之公平锁与非公平锁浅析
- [多线程_reentrantlock公平锁与非公平锁]
- ReentrantLock中公平锁与非公平锁的效率对比
- 【试验局】ReentrantLock中非公平锁与公平锁的性能测试
- java之ReentrantLock公平锁和非公平锁
- Java中ReentrantLock的公平锁和非公平锁
- Java之ReentrantLock公平锁和非公平锁
- ReentrantReadWriteLock重入锁中的读写锁在公平和非公平模式下的资源抢占测验
- Java多线程(九)之ReentrantLock与Condition
- Reetrantlock的公平非公平原理解析
- synchronized与lock 对象锁、互斥锁、共享锁以及公平锁和非公平锁
- ReentrantLock与公平锁、非公平锁实现
- java多线程:并发包中ReentrantLock锁的公平锁原理
- java并发库 Lock 公平锁和非公平锁
- java线程 公平锁 ReentrantLock(boolean fair)
- java线程 公平锁 ReentrantLock(boolean fair)