公平锁和非公平锁区别"/>
ReentrantLock和Synchronized区别,公平锁和非公平锁区别
1 ReentrantLock和synchronized区别
(1) synchronized 是Java的一个内置关键字,而ReentrantLock是Java的一个类。
(2) synchronized只能是非公平锁。而ReentrantLock可以实现公平锁和非公平锁两种。
(3) synchronized不能中断一个等待锁的线程,而Lock可以中断一个试图获取锁的线程。
(4) synchronized不能设置超时,而Lock可以设置超时。
(5) synchronized会自动释放锁,而ReentrantLock不会自动释放锁,必须手动释放,否则可能会导致死锁。
2 公平锁和非公平锁的区别
公平锁的获取锁的过程:
static final class FairSync extends Sync {final void lock() { // 1 注意对比公平锁和非公平锁的这个方法acquire(1);}public final void acquire(int arg) {if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();}protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {// 2 和非公平锁相比,这里多了一个判断:是否有线程在等待if (!hasQueuedPredecessors() &&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;}
}
非公平锁的获取锁的过程:
static final class NonfairSync extends Sync {final void lock() {// 1 和公平锁相比,这里会直接先进行一次CAS,如果当前正好没有线程持有锁,// 如果成功获取锁就直接返回了,就不用像公平锁那样一定要进行后续判断if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}public final void acquire(int arg) {if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();}protected final boolean tryAcquire(int acquires) {return nonfairTryAcquire(acquires);}
}final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {// 2 这里没有对阻塞队列进行判断if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;
}
从源码上看,可以看到公平锁和非公平锁的两个区别:
(1) 线程在获取锁调用lock()时,非公平锁首先会进行一次CAS尝试抢锁,如果此时没有线程持有锁或者正好此刻有线程执行完释放了锁(state == 0),那么如果CAS成功则直接占用锁返回。
(2) 如果非公平锁在上一步获取锁失败了,那么就会进入nonfairTryAcquire(int acquires),在该方法里,如果state的值为0,表示当前没有线程占用锁或者刚好有线程释放了锁,那么就会CAS抢锁,如果抢成功了,就直接返回了,不管是不是有其他线程早就到了在阻塞队列中等待锁了。而公平锁在这里抢到锁了,会判断阻塞队列是不是空的,毕竟要公平就要讲先来后到,如果发现阻塞队列不为空,表示队列中早有其他线程在等待了,那么公平锁情况下线程会乖乖排到阻塞队列的末尾。
如果非公平锁 (1)(2) 都失败了,那么剩下的过程就和非公平锁一样了。
(3) 从(1)(2) 可以看出,非公平锁可能导致线程饥饿,但是非公平锁的效率要高。
更多推荐
ReentrantLock和Synchronized区别,公平锁和非公平锁区别
发布评论