【原創】http://www.cnblogs.com/luoguoqiang1985
今天遇見了這問題,決定要需要討論下。
線程同步的方法:
- @synchronized
官方文檔解釋:The @synchronized directive is a convenient way to create mutex locks on the fly in Objective-C code.
個人理解:@synchronized關鍵字提供了互鎖功能。
示例代碼:
static NSObject *lockObj = nil; if (lockObj == nil) { lockObj = [[NSObject alloc] init]; } dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"A thread try lock!"); @synchronized(lockObj) { NSLog(@"A thread lock, please wait!"); [NSThread sleepForTimeInterval:10]; NSLog(@"A thread unlock!"); } }); dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"B thread try lock!"); @synchronized(lockObj) { NSLog(@"B thread lock, please wait!"); [NSThread sleepForTimeInterval:5]; NSLog(@"B thread unlock!"); } });
執行結果:
2013-12-28 21:11:02.332 Objc[1341:1b03] A thread try lock!
2013-12-28 21:11:02.335 Objc[1341:1b03] A thread lock, please wait!
2013-12-28 21:11:02.332 Objc[1341:3907] B thread try lock!
2013-12-28 21:11:12.336 Objc[1341:1b03] A thread unlock!
2013-12-28 21:11:12.336 Objc[1341:3907] B thread lock, please wait!
2013-12-28 21:11:17.337 Objc[1341:3907] B thread unlock!
實驗結果已經證明同步效果不錯!
- NSLock
官方解釋:An NSLock object is used to coordinate the operation of multiple threads of execution within the same application. An NSLock object can be used to mediate access to an application’s global data or to protect a critical section of code, allowing it to run atomically.
個人理解:在一個應用里面協調線程間的執行。
示例代碼:
昨晚鍵盤突然壞了,郁悶啊,早上趕緊入貨。繼續寫博了。
static NSLock *lockMain = nil; if (lockMain == nil) { lockMain = [[NSLock alloc] init]; } dispatch_async(dispatch_get_global_queue(0, 0), ^{
[lockMain lock];
NSLog(@"A thread begin +!");
[NSThread sleepForTimeInterval:10];
NSLog(@"A thread + done and unlock!");
[lockMain unlock];
[lockMain lock];
NSLog(@"A thread begin -!");
[NSThread sleepForTimeInterval:10];
NSLog(@"A thread - done and unlock!");
[lockMain unlock];
});
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[lockMain lock];
NSLog(@"B thread begin *!");
[NSThread sleepForTimeInterval:10];
NSLog(@"B thread * done and unlock!");
[lockMain unlock];
[lockMain lock];
NSLog(@"B thread begin /!");
[NSThread sleepForTimeInterval:10];
NSLog(@"B thread / done and unlock!");
[lockMain unlock];
});
執行結果:
2013-12-29 14:37:44.808 Objc[1219:1303] A thread begin +!
2013-12-29 14:37:54.811 Objc[1219:1303] A thread + done and unlock!
2013-12-29 14:37:54.812 Objc[1219:1d03] B thread begin *!
2013-12-29 14:38:04.813 Objc[1219:1d03] B thread * done and unlock!
2013-12-29 14:38:04.813 Objc[1219:1303] A thread begin -!
2013-12-29 14:38:14.815 Objc[1219:1303] A thread - done and unlock!
2013-12-29 14:38:14.816 Objc[1219:1d03] B thread begin /!
2013-12-29 14:38:24.817 Objc[1219:1d03] B thread / done and unlock!
- NSConditionLock
官方解釋:
The NSConditionLock class defines objects whose locks can be associated with specific, user-defined conditions. Using an NSConditionLock object, you can ensure that a thread can acquire a lock only if a certain condition is met. Once it has acquired the lock and executed the critical section of code, the thread can relinquish the lock and set the associated condition to something new. The conditions themselves are arbitrary: you define them as needed for your application.
個人理解:
根據條件加鎖與解鎖。
示例代碼:
static NSConditionLock *cdtLock = nil; #define A_THREAD 1 #define B_THREAD 2 #define C_THREAD 3 __block NSInteger a = B_THREAD; if (cdtLock == nil) { cdtLock = [[NSConditionLock alloc] initWithCondition:a]; } dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"A thread run!"); BOOL canLock = [cdtLock tryLockWhenCondition:A_THREAD]; if (!canLock) { NSLog(@"A Thread Lock fail,exit!"); return ; } NSLog(@"A thread begin lock!"); [NSThread sleepForTimeInterval:8]; NSLog(@"A thread unlock!"); [cdtLock unlock]; }); dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"B thread run!"); BOOL canLock = [cdtLock tryLockWhenCondition:B_THREAD]; if (!canLock) { NSLog(@"B Thread Lock fail,exit!"); return ; } NSLog(@"B thread begin lock!"); [NSThread sleepForTimeInterval:8]; NSLog(@"B thread unlock!"); [cdtLock unlock]; }); dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"C thread run!"); BOOL canLock = [cdtLock tryLockWhenCondition:C_THREAD]; if (!canLock) { NSLog(@"C Thread Lock fail,exit!"); return ; } NSLog(@"C thread begin lock!"); [NSThread sleepForTimeInterval:8]; NSLog(@"C thread unlock!"); [cdtLock unlock]; });
執行結果:
2013-12-29 20:46:27.426 Objc[6282:1303] A thread run!
2013-12-29 20:46:27.466 Objc[6282:1303] A Thread Lock fail,exit!
2013-12-29 20:46:27.426 Objc[6282:1e03] C thread run!
2013-12-29 20:46:27.468 Objc[6282:1e03] C Thread Lock fail,exit!
2013-12-29 20:46:27.426 Objc[6282:1c03] B thread run!
2013-12-29 20:46:27.481 Objc[6282:1c03] B thread begin lock!
- NSRecursiveLock 遞歸鎖
官方文檔:
NSRecursiveLock defines a lock that may be acquired multiple times by the same thread without causing a deadlock, a situation where a thread is permanently blocked waiting for itself to relinquish a lock. While the locking thread has one or more locks, all other threads are prevented from accessing the code protected by the lock.
個人理解:
同一個線程可以多次請求加鎖,但不會引起死鎖。
示例代碼:
static NSRecursiveLock *lock; if (lock == nil) { lock = [[NSRecursiveLock alloc] init]; } void (^__block DoLog)(int) = ^(int value){ [lock lock]; if (value > 0) { DoLog(value-1); } NSLog(@"value is %d", value); [lock unlock]; }; dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"test begin"); DoLog(5); NSLog(@"test end"); });
執行結果:
2013-12-29 21:15:31.567 Objc[6741:1303] test begin
2013-12-29 21:15:31.570 Objc[6741:1303] value is 0
2013-12-29 21:15:31.571 Objc[6741:1303] value is 1
2013-12-29 21:15:31.574 Objc[6741:1303] value is 2
2013-12-29 21:15:31.575 Objc[6741:1303] value is 3
2013-12-29 21:15:31.576 Objc[6741:1303] value is 4
2013-12-29 21:15:31.577 Objc[6741:1303] value is 5
2013-12-29 21:15:31.578 Objc[6741:1303] test end
block竟然也可以遞歸調用,神奇!