iOS開發(fā)-使用多線程同步鎖@synchronized()的注意事項

1.@synchronized原理

synchronized中傳入的object的內存地址,被用作key,通過hash map對應的一個系統(tǒng)維護的遞歸鎖。所以不管是傳入什么類型的object,只要是有內存地址,就能啟動同步代碼塊的效果。

2.注意事項

  • synchronized是使用的遞歸mutex來做同步。
 NSObject *obj = [[NSObject alloc]init];
    @synchronized (obj) {
        NSLog(@"1st sync");
        @synchronized (obj) {
            NSLog(@"2nd sync");
        }
    }

執(zhí)行結果:

2019-07-15 17:59:27.398820+0800 xxtest[63251:2852986] 1st sync
2019-07-15 17:59:27.399013+0800 xxtest[63251:2852986] 2nd sync
  • @synchronized(nil)不起任何作用
    @synchronized(nil)不起任何作用,表明我們需要適當關注傳入的object的聲明周期,一旦置為nil之后就無法做代碼同步了。
  • 慎用@synchronized(self) (盡量不要這樣使用)
    不要使用@synchronized(self)。
    不少代碼都是直接將self傳入@synchronized當,容易導致死鎖的出現(xiàn)。
//class A
@synchronized (self) {
    [_sharedLock lock];
    NSLog(@"code in class A");
    [_sharedLock unlock];
}

//class B
[_sharedLock lock];
@synchronized (objectA) {
    NSLog(@"code in class B");
}
[_sharedLock unlock];

原因是self很可能會被外部對象訪問,被用作key來生成一鎖,類似上述代碼中的@synchronized (objectA)。兩個公共鎖交替使用的場景就容易出現(xiàn)死鎖。

正確的做法是傳入一個類內部維護的NSObject對象,而且這個對象是對外不可見的。

  • 注意粒度控制
@synchronized (sharedToken) {
    [arrA addObject:obj];
}

@synchronized (sharedToken) {
    [arrB addObject:obj];
}

使用同一個token來同步arrA和arrB的訪問,雖然arrA和arrB之間沒有任何聯(lián)系。
應該是不同的數(shù)據(jù)使用不同的鎖,盡量將粒度控制在最細的程度
應該優(yōu)化成如下代碼:

@synchronized (tokenA) {
    [arrA addObject:obj];
}

@synchronized (tokenB) {
    [arrB addObject:obj];
}
  • 注意內部的函數(shù)調用
    @synchronized還有個很容易變慢的場景,就是{}內部有其他隱蔽的函數(shù)調用。比如:
@synchronized (tokenA) {
    [arrA addObject:obj];
    [self doSomethingWithA:arrA];
}

doSomethingWithA內部可能又調用了其他函數(shù),維護doSomethingWithA的工程師可能并沒有意識到自己是被鎖同步的,由此層層疊疊可能引入更多的函數(shù)調用,代碼就莫名其妙的越來越慢了,感覺鎖的性能差,其實是我們沒用好。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,658評論 1 32
  • 在上篇多線程安全的文章中,我曾推薦過大家使用@synchronized來使得代碼獲得原子性,從而保證多線程安全。這...
    MrPeak閱讀 8,096評論 10 59
  • Java多線程學習 [-] 一擴展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 3,108評論 1 18
  • @synchronized 是遞歸鎖,類似NSRecursiveLock,遞歸調用不會引起死鎖,而NSLock是非...
    RunningTeemo閱讀 495評論 0 0
  • 上了桌的菜如果都是多鹽多辣,最后一道湯,或者青菜,就可以偷偷不放鹽,并沒人察覺。 外婆紅燒肉做的好,在乎的是放冰糖...
    夏愛東西閱讀 381評論 0 3

友情鏈接更多精彩內容