GCD源碼解析

GCD源碼解析

dispatch_once_t

  • typedef long dispatch_once_t ??芍猟ispatch_once_t本質(zhì)是一個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真正執(zhí)行
              dispatch_atomic_barrier();
              *val = ~0l;
          } 
          else 
          {
              do
              {
                  _dispatch_hardware_pause();
              } while (*vval != ~0l);
              dispatch_atomic_barrier();
          }
      }
  • dispatch_atomic_cmpxchg 本質(zhì)是調(diào)用的__sync_bool_compare_and_swap((p), (o), (n))。一種原子操作機制,原理是如果p==0,則直接將p設(shè)置為n,返回true。否則不做任何處理,返回false。CSA方法。通過對CPU的操作保證原子性
  • 多線程的環(huán)境下,某個線程A首次進入dispatch_once_f ,*val == 0 ,這個時候會將val的值設(shè)置為1,其他的線程進入的話,會等待block的執(zhí)行完畢。將val設(shè)置為~0L(0xffffffff)。
  • dispatch_atomic_barrier(); 為了讓block執(zhí)行完畢再執(zhí)行更新數(shù)值的操作。
  • 再次進入的時候由于val變量指向內(nèi)存的值已經(jīng)更改為~0L.則直接會執(zhí)行else退出。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容