赞
踩
大家好,我是wave。这次我们继续接着讲锁,来给大家聊一聊Lock的一些底层原理。
public class Solution { static int n = 0; public static void main(String[] args)throws Exception { //创建一个Lock对象 Lock lock = new ReentrantLock(); //创建10个线程对n自加10000 for (int i = 0; i < 10; i++) { new Thread(()->{ //加锁 lock.lock(); try { for (int j = 0; j < 10000; j++) { n++; } }catch (Exception e){ e.printStackTrace(); }finally { //解锁 lock.unlock(); } }).start(); } Thread.sleep(3000); System.out.println(n);//100000 } }
- 这个代码案例就是创建了10个线程对一个变量n进行自加10000的操作,然后使用了Lock进行加锁,最后结果是正确的100000。
- 可以看到这里Lock加锁的逻辑代码加了一个try-catch块,这里并不是必须的一个异常捕获,但是Lock比较标准的写法就是最好使用try-catch块写入业务逻辑,最后在finally中进行unlock(解锁)。这样做的好处是避免某个线程突然发生异常,导致后面的unlock代码没有执行,就会造成死锁。
- 本篇文章主要讨论的是Lock的实现类ReentrantLock。
进入到lock()方法中,并找到ReentrantLock的实现方法
public void lock() {
sync.lock();
}
继续进入lock()
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* Performs {@link Lock#lock}. The main reason for subclassing
* is to allow fast path for nonfair version.
*/
abstract void lock();
这里我们发现Sync是一个继承了AbstractQueuedSynchronizer的类,AbstractQueuedSynchronizer就是我们常说的AQS,所以说Lock的底层使用的是AQS框架。AQS的细节我们后面继续说。
继续看lock()抽象方法的实现类,我们先选择看公平锁。
final void lock() {
acquire(1);
}
接着看 acquire(1),这个方法的tryAcquire、acquireQueued、addWaiter都会详细分析
public
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。