Lock()是怎么实现的

在并发编程中,经常会申请一块代码去加锁操作,比如new Reentrantlock().lock();

需求一:假设我们有十个线程t1-t10同时到达临界区,只有一个线程能获取锁,其余线程只能等待其释放锁才有机会去获得锁。

对于这么一个需求,如果是你该如何去设计lock()这个方法来满足以上需求?

1.设计一个状态 volatile state = 0;

2.当第一个线程调用lock方法,那么立马设置state值为1,表示获取了锁;如果当前线程再次获取锁也就是重入锁,那么state++;

大致思路  if(cas(state,1));如果成功则表示获得锁,假设t1获得锁,不会被阻塞,直接进入临界区。

3.其他线程调用lock方法,发现state已经被人修改不为0,那么放弃获取锁,把自己丢到一个等待队列里面,等待别人唤醒自己;

其他线程同样判断 if(cas(state,1));只要t1没有释放,state不为0,判断结果肯定是false,那么进入到等待队列。

需求二:线程1结束了任务释放锁,那么如何去通知其他线程?

其实这里又出现两种情况,公平锁与非公平锁。如果是公平锁那么一旦线程1任务结束,将会去唤醒等待队列里等待最久的元素,也就是

需要先进先出队列来满足这种需求。如果是非公平锁,那么会出现插队的情况产生,也就是任务1刚好结束的时候又来个一个线程11,该线程

会调用cas(state,1),恰好成功(其实几率很小),那么11线程就会优先于等待中的9个线程先执行.

我们还是没有解释清楚唤醒的过程,首先线程1结束任务,会调用new Reentrantlock().unlock()也就是告诉AQS我任务结束了,让GC回收我吧!

unlock方法会取设置最原始的state-1,同时找到等待队列里的head元素,也就是队首,也就是等待最久的那个元素,然后locksupport.unpark(head);

把队首元素唤醒,这样整个唤醒大致就完成了!

 

posted @ 2017-07-20 00:03  蒋贤军  阅读(482)  评论(0编辑  收藏  举报