GCD源码解析

GCD源码解析

dispatch_once_t

  • typedef long dispatch_once_t 。可知dispatch_once_t本质是一个long类型。

    • void dispatch_once(dispatch_once *val,void (^block)(void)){
          struct Block_basic *bb = (void *)(block);
          dispatch_once_f(val,block,(void *)bb->Block_invoke)
      }
      
  • 下面我们来看保障实例唯一的核心方法dispatch_once_f

      void dispatch_once_f(dispatch_once_t *val, void *ctxt, void (*func)(void *)){
          
          volatile long *vval = val;
          if (dispatch_atomic_cmpxchg(val, 0l, 1l)) {
              func(ctxt); // block真正执行
              dispatch_atomic_barrier();
              *val = ~0l;
          } 
          else 
          {
              do
              {
                  _dispatch_hardware_pause();
              } while (*vval != ~0l);
              dispatch_atomic_barrier();
          }
      }
  • dispatch_atomic_cmpxchg 本质是调用的__sync_bool_compare_and_swap((p), (o), (n))。一种原子操作机制,原理是如果p==0,则直接将p设置为n,返回true。否则不做任何处理,返回false。CSA方法。通过对CPU的操作保证原子性
  • 多线程的环境下,某个线程A首次进入dispatch_once_f ,*val == 0 ,这个时候会将val的值设置为1,其他的线程进入的话,会等待block的执行完毕。将val设置为~0L(0xffffffff)。
  • dispatch_atomic_barrier(); 为了让block执行完毕再执行更新数值的操作。
  • 再次进入的时候由于val变量指向内存的值已经更改为~0L.则直接会执行else退出。

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