iOS 單例模式

來源:互聯網
上載者:User

    最近在iOS開發中,需要用到單例模式,於是自己動手寫了一個,它看起來是這樣的:

<1>

+ (id)sharedInstance{    static id sharedInstance = nil;        if (!sharedInstance) {        sharedInstance = [[NSObject alloc] init];    }        return sharedInstance;}

    後來發現許多書上的做法都使用到了BOOL變數作為標值位,它看起來是這樣的:

<2>

+ (id)sharedInstance{    static id sharedInstance = nil;    static BOOL token = NO;        if (!token) {        token = YES;                sharedInstance = [[NSObject alloc] init];    }        return sharedInstance;}

    但是參考了蘋果官方的單例模式代碼,發現它看起來是這樣的:

<3>

+ (id)sharedInstance{    static id sharedInstance;    static dispatch_once_t onceToken;        dispatch_once(&onceToken, ^{        sharedInstance = [[NSObject alloc] init];    });        return sharedInstance;}

    那麼它們究竟有多大區別呢?

    原來,它們的區別在於多線程並發時的表現。

    <1>使用了一個指標變數作為標誌位,這在多線程並發時是不可取的,因為sharedInstance = [[NSObject alloc] init];這行代碼的執行本身是需要時間的。很可能有兩個線程同時進入到了這行代碼,而這將導致記憶體流失。

    <2>使用的標誌位是一個BOOL變數,當多線程並發時,會出現1線程判斷為NO,開始alloc並做賦值操作,但是2線程進入時判斷為YES,而1線程賦值操作還沒執行結束,這時候2線程會拿到一個nil。儘管它不會造成記憶體流失,但是它會有相當多的線程擷取不到對象。

    <3>使用了dispatch_once函數。這個函數來自於Grand Central Dispatch (GCD),Apple自Mac OS 10.6 / iOS 4.0引用了它。

    該函數接收一個dispatch_once_t用於檢查該代碼塊是否已經被調度的謂詞(是一個長整型,實際上作為BOOL使用)。它還接收一個希望在應用的生命週期內僅被調度一次的代碼塊。這不僅意味著代碼僅會被運行一次,而且還是安全執行緒的,你不需要使用諸如@synchronized之類的來防止使用多個線程或者隊列時不同步的問題。

    Apple的GCD Documentation證實了這一點:

    如果被多個線程調用,該函數會同步等等直至代碼塊完成。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.