首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Java并发编程-AbstractQueuedSynchronizer源码分析(9)

Java并发编程-AbstractQueuedSynchronizer源码分析(9)

public final void acquireShared(int arg)调用该方法能够以共享模式获取状态,共享模式和之前的独占模式有所区别。以文件的查看为例,如果一个程序在对其进行读取操作,那么这一时刻,对这个文件的写操作就被阻塞,相反,这一时刻另一个程序对其进行同样的读操作是可以进行的。如果一个程序在对其进行写操作,那么所有的读与写操作在这一时刻就被阻塞,直到这个程序完成写操作。
以读写场景为例,描述共享和独占的访问模式,如下图所示:

上图中,红色代表被阻塞,绿色代表可以通过。
[url=][/url]
01    public final void acquireShared(int arg) {02        if (tryAcquireShared(arg) < 0)   doAcquireShared(arg); } private void doAcquireShared(int arg) {     
  
             final Node node = addWaiter(Node.SHARED);  
             boolean failed = true;  
  
             try {      
      
                      boolean interrupted = false;        

                   for (;;) {         

                          final Node p = node.predecessor();        
                          if (p == head) {              
                                int r = tryAcquireShared(arg);              

                            if (r >= 0) {03                        setHeadAndPropagate(node, r);04                        p.next = null; // help GC05                        if (interrupted)06                            selfInterrupt();07                        failed = false;08                        return;09                    }10                }11                if (shouldParkAfterFailedAcquire(p, node) &&12    parkAndCheckInterrupt())13                interrupted = true;14            }15        } finally {16            if (failed)17                cancelAcquire(node);18        }19    }[url=][/url]






上述逻辑主要包括:
1. 尝试获取共享状态;
调用tryAcquireShared来获取共享状态,该方法是非阻塞的,如果获取成功则立刻返回,也就表示获取共享锁成功。
2. 获取失败进入sync队列;
在获取共享状态失败后,当前时刻有可能是独占锁被其他线程所把持,那么将当前线程构造成为节点(共享模式)加入到sync队列中。
3. 循环内判断退出队列条件;
如果当前节点的前驱节点是头结点并且获取共享状态成功,这里和独占锁acquire的退出队列条件类似。
4. 获取共享状态成功;
在退出队列的条件上,和独占锁之间的主要区别在于获取共享状态成功之后的行为,而如果共享状态获取成功之后会判断后继节点是否是共享模式,如果是共享模式,那么就直接对其进行唤醒操作,也就是同时激发多个线程并发的运行。
5. 获取共享状态失败。
通过使用LockSupport将当前线程从线程调度器上摘下,进入休眠状态。
对于上述逻辑中,节点之间的通知过程如下图所示:

上图中,绿色表示共享节点,它们之间的通知和唤醒操作是在前驱节点获取状态时就进行的,红色表示独占节点,它的被唤醒必须取决于前驱节点的释放,也就是release操作,可以看出来图中的独占节点如果要运行,必须等待前面的共享节点均释放了状态才可以。而独占节点如果获取了状态,那么后续的独占式获取和共享式获取均被阻塞。
返回列表