夜光带你走进 Java 成神之路(四十五)擅长的领域

编程入门 行业动态 更新时间:2024-10-10 04:22:17

夜光<a href=https://www.elefans.com/category/jswz/34/1769690.html style=带你走进 Java 成神之路(四十五)擅长的领域"/>

夜光带你走进 Java 成神之路(四十五)擅长的领域

夜光序言:

 

深有体会~

人生之路是逼着走出来的,不逼自己一把,就永远不知道自己能做多大的事。

切断了退路,自然会想办法寻找出路;

掐断了幻想,才会埋头苦干。

逼着自己走出第一步,第二步、第三步就容易多了。

如果不逼自己,懒惰就会逐渐锈蚀自己的心,曾经的豪情万丈也会灰飞烟灭,生命的价值将会大打折扣。

 

 

 

 

 

 

 

 

 

正文:

                           以道御术 / 以术识道

ReentrantLock和synchronized

我们发现在实际开发中,看情况,并没有哪一种用的特别多

我更倾向于synchronized


并发编程不像ssm和ssh

还有什么实战,给你开发一个什么什么管理系统或者登陆

 

面试造火箭,实际工作拧螺丝

 

 

 

 

 

 

 

并发编程真正想搞明白

还是需要去看源码

 

ReentrantLock源码详细解读

AbstractQueuedSynchronizer(AQS源码解读)

大家可以有针对性的理解思考一下上面的问题

上面这个图很形象的介绍了各个关系

这里提一提:软件工程是一门科学,很多东西都需要我们程序员去实践,什么spring、springboot、springcloud,我们可以通过培训或者自学很容易入门

但是并发编程需要深入到里面下能有所体会,需要自己去实践

没有看源码,很多东西道听途说都是没用的~~~


 

Windows不开源

很多东西,我们都要学习linux

 

 

 

   

    首先呢:Sync:是提供AQS实现的工具,类似于适配器,提供了抽象的lock(),便于快速创建非公平锁。
    FairSync(公平锁):线程获取锁的顺序和调用lock()的顺序一样,FIFO。即先到先得


    NoFairSync(非公平锁):线程获取锁的顺序和调用lock()的顺序无关,抢到CPU的时间片即可调度。


这里,我们需要提一提:ReentrantLock中的重要方法

构造方法:无参构造方法,我们可以意识到 → 默认创建非公平锁;但是呢~~

有参构造方法,并且fair==true时,创建公平锁。
 


// 这里,我们可以看到
//维护了一个Sync,对于锁的操作
//我们发现,都交给sync来处理private final Sync sync;   public ReentrantLock() {sync = new NonfairSync();}public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}

这里需要提一提:获取资源资源(锁)的方法

请求都是交给Sync来调度的。

    //首先呢
//    可以发现:请求锁资源,会阻塞且不处理中断请求,//这里,我们做一个假设,如果没有调用unLock(),则会一直被阻塞。public void lock() {sync.lock();}
//其次呢
//很重要的一个概念//有一种情况:线程在请求lock并被阻塞时
//这里,如果被interrupt,则此线程会被唤醒并被要求处理public void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);}
//我们继续往下面看
////尝试获取锁,默认获取的是非公平锁,失败后不会阻塞//直接返回true或falsepublic boolean tryLock() {return sync.nonfairTryAcquire(1);}//这里,我们需要提一提 → 重载方法,在规定时间内获取锁,获取不到则返回falsepublic boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));}

嗯唔~~      锁肯定需要释放,我们释放资源(锁)的方法:

不管是公平还是非公平锁,我们都会调用AQS.release(1)这个方法~~

给当前线程持有锁的数量-1。

//释放锁,给当前线程持有锁的数量-1  public void unlock() {sync.release(1);}

 

 

嗯唔~~

那个:主要讲非公平锁与公平锁获取资源的方法,因为释放资源的逻辑是一样的。

Sync来获取资源

我们需要知道:sync中定义了获取资源的总入口。但是呢,具体的调用还是看实现类是什么。

//调用的方法
abstract void lock();

 

我们看一看:非公平锁获取资源

嗯唔,看一看lock():获取锁时调用AQS的CAS方法,是阻塞的。

如果获取成功,则把当前线程设置为锁的持有者;如果获取失败,则通过AQS.acquire()获取锁。

 

我们程序员之前通过AQS源码详细解读,了解到acquire()中使用了模板模式,调用子类的tryAcquire()尝试获取锁

 

如果tryAcquire()返回false,则进入等待队列自旋获取,这之后呢,再判断前驱的waitStatus【这是一个很重要的概念】,判断是否需要被阻塞等。
 

 

tryAcquire():走的是Sync.nofairTryAcquire()。

    
//我们看一看这个代码嗯
//tryAcquire  布尔类型protected final boolean tryAcquire(int acquires) {return nonfairTryAcquire(acquires);}

我们再来看看下面这一段代码:

 

        final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();
//这里,我们备注一个注释//state是0,锁处于空闲状态,使用CAS获取if (c == 0) {if (compareAndSetState(0, acquires)) {//获取成功后,当前线程就是锁的持有者setExclusiveOwnerThread(current);return true;}}//这里呢,获取失败则先判断当前线程是否是锁的持有者//这里很重要,也是ReentrantLock实现可重入的原因else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;//可以看出源码设计者的厉害之处,考虑到了锁溢出的情况if (nextc < 0) throw new Error("Maximum lock count exceeded");//这里呢          我们将当前线程持有的锁+1setState(nextc);return true;}return false;}

 

nonfairTryAcquire(int acquires):这是什么意思呢,表示如果锁空闲,则用CAS修改state;

 

如果锁被占用,则判断占有者是不是自己,实现可重入。

那么~~          最终没有获取锁到就返回false。


 

下面,我们再看看:如何运用公平锁获取资源

lock():也是阻塞的。这里需要注意一下:

与非公平锁的区别是,我们呢~~

不能直接通过CAS修改state,而是直接走AQS.acquire()。

 

//方法差不多就是这样嗯
//参数为1     final void lock() {acquire(1);}

 

这里,我们看一看          →        tryAquire():与非公平锁类似,AQS.acquire()会调用这个钩子方法。

但是呢,我们发现多判断了hasQueuedPredecessors(),判断当前节点在等待队列中是否有前驱节点,如果有,则说明有线程比当前线程更早的请求资源,根据公平性

 

嗯唔~~         当前线程请求资源失败;如果当前节点没有前驱节点,才有做后面的逻辑判断的必要性。
 


 

        protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {//下面这段源代码,很多老师都讲过该如何理解//我们可以看一下//!hasQueuedPredecessors()判断等待队列中是否有前驱节点,没有则尝试获取锁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;}

 

下面,我们看一下:

ReentrantLock有三种获取锁的方法,lock(),tryLock(),lockInterruptibly()。

 

这里我们提一提获取资源   →  tryLock():走的还是sync的方法,主要是在指定时间内获取锁,直接返回结果。


    
// tryLock():走的还是sync的方法,主要是在指定时间内获取锁,直接返回结果。
public boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));}
    
//我们看看下面这一段代码
//看看如何理解
public final boolean tryAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {
//tryAcquireNanos():如果调用tryLock的规定时间内尝试方法,就会调用该方法
//挺有意思的
//这里,我们先判断是否中断,然后尝试获取资源,否则进入AQS.doAcquireNanos()
//在规定时间内自旋拿资源,[这里注意一下:自旋的次数是由计算机学者决定的]
//拿不到则挂起再判断是否被中断。if (Thread.interrupted())throw new InterruptedException();return tryAcquire(arg) ||doAcquireNanos(arg, nanosTimeout);}

嗯唔~~         这里我们看一下:lockInterruptibly()--获取锁时响应中断

lockInterruptibly():交给了调度者sync执行。

    //我们看一下这个方法public void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);}

 

我们看一下:acquireInterruptibly()    →    嗯唔~~这里当尝试获取锁失败后,之后,我们就进行阻塞可中断的获取锁的过程。

这里,我们调用AQS.doAcquireInterruptibly()这个方法

很厉害嗯~~


 

  //我们看下下面这个方法
// Thread.interrupted() 阻塞public final void acquireInterruptibly(int arg)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();if (!tryAcquire(arg))doAcquireInterruptibly(arg);}

我们可以知道:公平锁与非公平锁的释放都是一样的。

我们可以知道:ReentrantLock.release()调用的是sync.release(1)。

所以呢:本质还是进入AQS.release(1),下面看看其中的tryRelease()这个钩子方法如何实现。


嗯唔~~:Sync释放资源

tryRelease():尝试释放锁,彻底释放后返回true。
 

        protected final boolean tryRelease(int releases) {int c = getState() - releases;//需要注意一下:释放锁必须保证当前线程是锁的持有者if (Thread.currentThread() != getExclusiveOwnerThread())throw new IllegalMonitorStateException();boolean free = false;//注意看下状态值//如果释放后状态值为0,则彻底释放,持有者被设置为空if (c == 0) {free = true;setExclusiveOwnerThread(null);}//嗯唔//设置释放后的statesetState(c);return free;}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

更多推荐

夜光带你走进 Java 成神之路(四十五)擅长的领域

本文发布于:2024-02-27 13:40:24,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1706754.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:带你   神之   领域   Java   四十五

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!