原文為 堤刻科技技術長 分享給同仁的信件
--------------------
今天重新再看過一次一些比較基本的 document, 把死背的東西部分的重新消化過一次,
其中有一個可能比較有趣的地方應該是 NSLock 和 @synthesize, 如果這個世界只有單 thread,
那麼我的 function 只要這樣寫
-(void) myFunction {
NSLog(@"%d", count++);
}
然後我用一個 for 到 100 的迴圈去跑他的時候, 他可以按照順序的從 0~99 乖乖的排好,
但是當我 thread 變多的時候, 同時間衝進來拿到 count 這個數字的人可能就不只有一個,
所以通常的狀況就會是跑不滿到數字 99 就停了, 這個 function 有被執行 100 次,
只是最後的數字不會是 99.
在 obj-c 裡面提供了一個簡單而好用的做法, 讓開發者可以不用花太多心力,
而能保持同一個程式碼區段的單一性, 只要在這個 function 裡面的部份加上
-(void) myFunction {
@synchronized (self) {
NSLog(@"%d", count++);
}
}
那麼, 數字又會乖乖的從 0~99 排好, 即使是在 multi-thread 的情況下,
但是, 如果我把這段程式碼改成用 NSLock 來表達會變得怎麼樣?
假想起來會是這麼寫的
-(void) myFunction {
if ([lock tryLock]) {
NSLog(@"%d", count++);
[lock unlock];
}
}
想起來還蠻合理的, 就是當有人進來, 我就試試能不能鎖, 可以鎖的話我就開始做,
等做完之後再把他解鎖給下一個人用, 但是其實錯了~ O3O
因為在 multi-thread 的情況下, 所有的人都直接衝進這個 function, 當第一個人進去之後,
他就把門鎖上, 其他的人都因為進不去, 直接的就結束 function 了, 因此,
只會被 run 一次, 如果要從 NSLock 去做到 @synchronized的效果也是可以,
不過就要花費更多的程式碼在這上面, 不如使用 @synchronized.
所以雖然都是保護程式碼區塊的功能, 但是他們還是有些微的差異,
當我想要每一個進來這個 function 的人都依序執行的話, 那麼選擇用 @synchronized
當我想要防止這個 function 重複 call, 還沒有執行完就猛摳猛摳的囉嗦鬼, 那麼選擇用 NSLock
因為在 multi-thread 的情況下, 所有的人都直接衝進這個 function, 當第一個人進去之後,
回覆刪除他就把門鎖上, 其他的人都因為進不去, 直接的就結束 function 了
这个结论是错误的,
那是因为你nslock的用法错误了
-(void) myFunction {
if ([lock tryLock]) {
NSLog(@"%d", count++);
[lock unlock];
}
}
你使用了tryLock,所以拿不到锁自然就结束了
应该使用lock即可,只要lock没有被释放,后面的访问都会等待该lock被释放而不会立即结束