【线程】ReentrantLock 内部公平锁与非公平锁实现 (十)

我的原则:先会用再说,内部慢慢来


一、概念

  1. 公平锁: 遵循FIFO,先来先服务的原则。
  2. 非公平锁: 哄抢锁,谁先抢到服务谁。

二、ReentrantLock 架构

在这里插入图片描述

三、FailSync 与 NonfairSync 核心代码区别

  1. 根据 AQS 实现类的不同,FairSync + NonfairSync 的tryAcquire实现不同
  2. Sync#nonfairTryAcquire 非公平模式获取锁方法
  3. FairSync#tryAcquire 公平模式获取锁方法
  1. AbstractQueuedSynchronizer#acquire 方法
public final void AbstractQueuedSynchronizer#acquire(int arg) {
	/* 
	 * 根据 AQS 实现类的不同,FairSync + NonfairSync 的tryAcquire实现不同
	 * 1. NonfaireSync 在 tryAcquire 很大几率获得锁 ,不往下走了
	 * 2。 FairSync 在 tryAcquire ,若遇到Sync队列有Node,那么就直接获取失败,进入 acquireQueued 去排队。
	 */
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}
  1. Sync#nonfairTryAcquire 非公平模式获取锁方法
final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
    	// 公平锁与非公平锁区别就在这,非公平锁模式下,一会机会直接就去争夺锁了。无需FIFO
        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;
}
  1. FairSync#tryAcquire 公平模式获取锁方法
protected final boolean FairSync#tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
    	// 公平锁与非公平锁区别就在这,公平锁模式下,抢夺锁之前,会去判断同步队列里面是否有线程等待,有的话,就去排队
        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;
}

在这里插入图片描述

四、代码 demo

  1. FairSync 模式
public class _12_02_TestCondition {
	public static void main(String[] args) throws Exception{
		LockDemo lockDemo = new LockDemo();
		for (int i = 0; i < 5; i++) {
			new Thread(() -> {
				try {
					lockDemo.await();
				} catch (Exception e) {
					e.printStackTrace();
				}
			},"A" + i).start();
		}
		// 确保上面代码先执行
		Thread.sleep(1000);
		Scanner sc = new Scanner(System.in);
		System.out.println("点击任意键唤醒线程 ...");
		sc.nextLine();

		for (int i = 0; i < 5; i++) {
			new Thread(() -> {
				lockDemo.signal();

			},"B" + i).start();
		}
	}
	static class LockDemo{
		ReentrantLock lock = new ReentrantLock(true);
		Condition condition = lock.newCondition();
		public void await() throws Exception{
			System.out.println(Thread.currentThread().getName() + ",condition ready to lock ===");
			lock.lock();
			System.out.println(Thread.currentThread().getName() + ",condition ready to await ");
			condition.await();
			System.out.println(Thread.currentThread().getName() + ",condition ready to unlock ===");
			lock.unlock();
		}
		public void signal(){
			System.out.println(Thread.currentThread().getName() + ",condition ready to lock ");
			lock.lock();
			System.out.println(Thread.currentThread().getName() + ",condition ready to signal ");
			condition.signal();
			System.out.println(Thread.currentThread().getName() + ",condition ready to unlock ");
			lock.unlock();
		}
	}
}
    1. FairSync 模式下输出:
A0,condition ready to lock ===
A1,condition ready to lock ===
A0,condition ready to await 
A2,condition ready to lock ===
A3,condition ready to lock ===
A4,condition ready to lock ===
A1,condition ready to await 
A2,condition ready to await 
A3,condition ready to await 
A4,condition ready to await 
点击任意键唤醒线程 ...


B0,condition ready to lock 
B0,condition ready to signal 
B0,condition ready to unlock 
B1,condition ready to lock 
A0,condition ready to unlock ===
B2,condition ready to lock 
B1,condition ready to signal 
B1,condition ready to unlock 
B3,condition ready to lock 
B2,condition ready to signal 
B2,condition ready to unlock 
A1,condition ready to unlock ===
B4,condition ready to lock 
B3,condition ready to signal 
B3,condition ready to unlock 
A2,condition ready to unlock ===
B4,condition ready to signal 
B4,condition ready to unlock 
A3,condition ready to unlock ===
A4,condition ready to unlock ===
  1. 改成 NonfairSync 模式

ReentrantLock lock = new ReentrantLock(); // 默认非公平锁

  1. NonfairSync 模式下输出
A0,condition ready to lock ===
A1,condition ready to lock ===
A2,condition ready to lock ===
A0,condition ready to await 
A3,condition ready to lock ===
A3,condition ready to await 
A1,condition ready to await 
A2,condition ready to await 
A4,condition ready to lock ===
A4,condition ready to await 
点击任意键唤醒线程 ...


B0,condition ready to lock 
B1,condition ready to lock 
B0,condition ready to signal 
B0,condition ready to unlock 
B2,condition ready to lock 
B2,condition ready to signal 
B2,condition ready to unlock 
B3,condition ready to lock 
B1,condition ready to signal 
B4,condition ready to lock 
B1,condition ready to unlock 
A0,condition ready to unlock ===
A3,condition ready to unlock ===
B3,condition ready to signal 
B3,condition ready to unlock 
A1,condition ready to unlock ===
B4,condition ready to signal 
B4,condition ready to unlock 
A2,condition ready to unlock ===
A4,condition ready to unlock ===

结论:

ReentrantLock lock = new ReentrantLock(true); 公平锁模式下,谁先 lock ,谁就先 unlock。
ReentrantLock lock = new ReentrantLock(); 非公平锁模式下,不一定。

五、番外篇

下一章节:【线程】ReentrantReadWriteLock 内部共享锁与排他锁源码分析 (十一)
上一章节:【线程】ReentrantLock + Condition 源码剖析 (九)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值