深入理解ThreadPoolExecutor的addWorker()来保证同步

分解addWorker()函数—第一块如下

当我们在多个线程对于全局的excutor对象提交任务是如何保证同步的

  • 关键点在于保证获取到的核心线程数目workerCountOf©是最新的,如何不加锁完成这一点
  • 通过 核心线程 1 的例子说明
注意两层循环------------
     ###########################################
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);
            获取最新的ctl,但是无法保证不被后来线程修改
     #################################################       

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;
                状态判断只有running和shutdown+ firstTask == null+ workQueue不为空能通过
  ####################################################    
              内部循环:为了判断修改核心线程 
                通过一步cas
 ####################################################   
            for (;;) {
                int wc = workerCountOf(c);
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                     判断是否超过(core==true)corePoolSize 或者(core==false)maximumPoolSize,但是无法保证我们第一步获取到的值是否已经被修改
                     
####################################################   
                if (compareAndIncrementWorkerCount(c))
                    break retry;
     关键一步 :根据我们最近获取的值进行cas更新,成功说明我们获取到的就是最新的值,跳出2层循环,失败说明此值已经被别人修改过了,
     注意--》可能修改了状态也可能是线程数量,
############################################################   
                c = ctl.get();  // Re-read ctl
                更新获取到的ctl值############################################################   
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
             比较两次得到的值,如果是状态改变了跳出2层循环重新开始
             
####################################################   
  不是状态改变了,就是线程数目改变了继续本层循环
###################################################
        }
  • 注意两次循环,是为了提高效率,在状态未改变的情况下只需要继续cas修改就可以了,不用进行状态检查,如果中途状态又被修改,cas还是会失败—》continue到达上层循环

你可能感兴趣的:(源码分析)