1.Synchronized方式
h文件
@interface testLock : NSObject{
? ?NSString *mStr;
}
- (void)testSynchronized:(NSString *)str;
@implementation testLock
- (void)testSynchronized:(NSString *)str{
? ?@synchronized (mStr) {
? ? ? ?NSLog(@"testSynchronized_1,str:%@",str);
? ? ? ?NSLog(@"testSynchronized_2,str:%@",str);
? ? ? ?NSLog(@"testSynchronized_3,str:%@",str);
? ? ? ?NSLog(@"testSynchronized_4,str:%@",str);
? ? ? ?mStr = str;
? ? ? ?}
}
main函數:
testLock *tempLock = [[testLock alloc] init:@"temp"];
[tempLock testSynchronized:@"tempLocktestSynchronized"];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[tempLock testSynchronized:@"test1testSynchronized"];
});
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[tempLock testSynchronized:@"test2testSynchronized"];
});
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[tempLock testSynchronized:@"test3testSynchronized"];
});
輸出結果:
2016-06-12 15:20:30.870 TestRuntime[5407:398185] testSynchronized_1,str:tempLocktestSynchronized
2016-06-12 15:20:30.870 TestRuntime[5407:398185] testSynchronized_2,str:tempLocktestSynchronized
2016-06-12 15:20:30.870 TestRuntime[5407:398185] testSynchronized_3,str:tempLocktestSynchronized
2016-06-12 15:20:30.870 TestRuntime[5407:398185] testSynchronized_4,str:tempLocktestSynchronized
2016-06-12 15:20:30.870 TestRuntime[5407:398223] testSynchronized_1,str:test1testSynchronized
2016-06-12 15:20:30.871 TestRuntime[5407:398223] testSynchronized_2,str:test1testSynchronized
2016-06-12 15:20:30.871 TestRuntime[5407:398223] testSynchronized_3,str:test1testSynchronized
2016-06-12 15:20:30.871 TestRuntime[5407:398223] testSynchronized_4,str:test1testSynchronized
2016-06-12 15:20:30.871 TestRuntime[5407:398224] testSynchronized_1,str:test2testSynchronized
2016-06-12 15:20:30.871 TestRuntime[5407:398224] testSynchronized_2,str:test2testSynchronized
2016-06-12 15:20:30.871 TestRuntime[5407:398224] testSynchronized_3,str:test2testSynchronized
2016-06-12 15:20:30.871 TestRuntime[5407:398224] testSynchronized_4,str:test2testSynchronized
2016-06-12 15:20:30.871 TestRuntime[5407:398225] testSynchronized_1,str:test3testSynchronized
2016-06-12 15:20:30.871 TestRuntime[5407:398225] testSynchronized_2,str:test3testSynchronized
2016-06-12 15:20:30.871 TestRuntime[5407:398225] testSynchronized_3,str:test3testSynchronized
2016-06-12 15:20:30.871 TestRuntime[5407:398225] testSynchronized_4,str:test3testSynchronized
如果修改對應m文件的內容為:
- (void)testSynchronized:(NSString *)str{
@synchronized (mStr) {
? ?mStr = str;
? ?NSLog(@"testSynchronized_1,str:%@",str);
? ?NSLog(@"testSynchronized_2,str:%@",str);
? ?NSLog(@"testSynchronized_3,str:%@",str);
? ?NSLog(@"testSynchronized_4,str:%@",str);
? ?}
}
則輸出為:
2016-06-12 15:22:52.821 TestRuntime[5475:399682] testSynchronized_1,str:tempLocktestSynchronized
2016-06-12 15:22:52.821 TestRuntime[5475:399682] testSynchronized_2,str:tempLocktestSynchronized
2016-06-12 15:22:52.821 TestRuntime[5475:399682] testSynchronized_3,str:tempLocktestSynchronized
2016-06-12 15:22:52.821 TestRuntime[5475:399682] testSynchronized_4,str:tempLocktestSynchronized
2016-06-12 15:22:52.822 TestRuntime[5475:399717] testSynchronized_1,str:test1testSynchronized
2016-06-12 15:22:52.822 TestRuntime[5475:399718] testSynchronized_1,str:test2testSynchronized
2016-06-12 15:22:52.822 TestRuntime[5475:399717] testSynchronized_2,str:test1testSynchronized
2016-06-12 15:22:52.822 TestRuntime[5475:399719] testSynchronized_1,str:test3testSynchronized
2016-06-12 15:22:52.822 TestRuntime[5475:399718] testSynchronized_2,str:test2testSynchronized
2016-06-12 15:22:52.822 TestRuntime[5475:399717] testSynchronized_3,str:test1testSynchronized
2016-06-12 15:22:52.822 TestRuntime[5475:399719] testSynchronized_2,str:test3testSynchronized
2016-06-12 15:22:52.822 TestRuntime[5475:399719] testSynchronized_3,str:test3testSynchronized
2016-06-12 15:22:52.822 TestRuntime[5475:399718] testSynchronized_3,str:test2testSynchronized
2016-06-12 15:22:52.822 TestRuntime[5475:399717] testSynchronized_4,str:test1testSynchronized
2016-06-12 15:22:52.822 TestRuntime[5475:399719] testSynchronized_4,str:test3testSynchronized
2016-06-12 15:22:52.822 TestRuntime[5475:399718] testSynchronized_4,str:test2testSynchronized
從上面的結果可以看出,在對mStr變量做鎖定的時候,對mStr的值的改變的語句位置不同會造成@synchronized內部執行順序的不一樣,從輸出看,只要mStr的值已經被修改,則鎖就好像被釋放了?~
2.NSLock
NSLock * lock = [[NSLock alloc]init];
NSMutableArray * piaos = [NSMutableArray arrayWithArray:@[@"a",@"b",@"c"]];
// 線程1
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[lock lock];
NSLog(@"thread1:%@",piaos);
sleep(3);
[piaos removeObject:@"a"];
[lock unlock];
});
// 線程2
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[piaos removeObject:@"b"];
NSLog(@"thread2:%@",piaos);
});
// 線程3
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[lock lock];
NSLog(@"thread3:%@",piaos);
[lock unlock];
});
輸出:
2016-06-12 15:32:54.819 TestRuntime[5515:409045] thread1:(
a,
b,
c
)
2016-06-12 15:32:54.819 TestRuntime[5515:409046] thread2:(
a,
c
)
2016-06-12 15:32:57.819 TestRuntime[5515:409047] thread3:(
c
)
所有加相同鎖的內容只能按照 [lock lock]以及[lock unlock]的順序執行,對沒有加鎖的代碼片段沒有影響
3.NSConditionLock
NSConditionLock * lock = [[NSConditionLock alloc]init];
//Thread1
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (int i = 0; i< 4; i++) {
[lock lock];
NSLog(@"thread1");
[lock unlockWithCondition:i];
sleep(3);
}
});
// Thread2
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"thread2");
});
// Thread3
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[lock lockWhenCondition:3];
NSLog(@"thread3");
[lock unlock];
});
// Thread4
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[lock lockWhenCondition:2];
NSLog(@"thread4");
[lock unlock];
});
輸出:
2016-06-12 15:34:45.145 TestRuntime[5531:411155] thread2
2016-06-12 15:34:45.145 TestRuntime[5531:411154] thread1
2016-06-12 15:34:48.146 TestRuntime[5531:411154] thread1
2016-06-12 15:34:51.146 TestRuntime[5531:411154] thread1
2016-06-12 15:34:51.146 TestRuntime[5531:411155] thread4
2016-06-12 15:34:54.148 TestRuntime[5531:411154] thread1
2016-06-12 15:34:54.148 TestRuntime[5531:411156] thread3
滿足條件的時候可以lock和unlock,可以隨意組合:lock ,lockWhenCondition,unlock,unlockWithCondition
4.NSRecursiveLock
NSRecursiveLock *lock = [[NSRecursiveLock alloc]init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
static void (^RecursiveMethod)(int);
RecursiveMethod = ^(int value) {
[lock lock];
if (value > 0) {
NSLog(@"value = %d", value);
sleep(1);
RecursiveMethod(value - 1);
}
[lock unlock];
};
RecursiveMethod(5);
});
輸出:
2016-06-12 15:36:44.951 TestRuntime[5544:413127] value = 5
2016-06-12 15:36:45.955 TestRuntime[5544:413127] value = 4
2016-06-12 15:36:46.959 TestRuntime[5544:413127] value = 3
2016-06-12 15:36:47.961 TestRuntime[5544:413127] value = 2
2016-06-12 15:36:48.965 TestRuntime[5544:413127] value = 1
如果改用NSLock,發生死鎖則會輸出:
2016-06-12 15:38:15.877 TestRuntime[5558:414854] value = 52016-06-12 15:38:16.879 TestRuntime[5558:414854] *** -[NSLock lock]: deadlock ('(null)')
2016-06-12 15:38:16.880 TestRuntime[5558:414854] *** Break on _NSLockError() to debug.
NSRecursiveLock會跟蹤它被多少次lock。每次成功的lock都必須平衡調用unlock操作。只有所有的鎖住和解鎖操作都平衡的時候,鎖才真正被釋放給其他線程獲得;
5.NSCondition
NSCondition * lock = [[NSCondition alloc]init];
NSMutableArray * piaos = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3"]];
// Thread1
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[lock lock];
NSLog(@"Thread1,lock done");
[lock wait];
NSLog(@"Thread1,wait done");
[lock unlock];
NSLog(@"Thread1,unlock done");
});
// Thread2
dispatch_async(dispatch_get_global_queue(0, 0), ^{
static void (^clearTheObj)(NSMutableArray * array);
clearTheObj = ^(NSMutableArray * array){
NSLog(@"%lu",(unsigned long)array.count);
if ([array count]>0) {
[array removeObjectAtIndex:0];
}else{
[lock signal];
NSLog(@"Thread2,signal done");
return;
}
sleep(1);
clearTheObj(array);
};
[lock lock];
NSLog(@"Thread2,lock done");
clearTheObj(piaos);
NSLog(@"Thread2,clearTheObj done");
[lock unlock];
NSLog(@"Thread2,unlock done");
});
輸出:
2016-06-12 15:39:37.653 TestRuntime[5571:415857] Thread1,lock done
2016-06-12 15:39:37.653 TestRuntime[5571:415858] Thread2,lock done
2016-06-12 15:39:37.653 TestRuntime[5571:415858] 3
2016-06-12 15:39:38.657 TestRuntime[5571:415858] 2
2016-06-12 15:39:39.658 TestRuntime[5571:415858] 1
2016-06-12 15:39:40.658 TestRuntime[5571:415858] 0
2016-06-12 15:39:40.658 TestRuntime[5571:415858] Thread2,signal done
2016-06-12 15:39:40.658 TestRuntime[5571:415858] Thread2,clearTheObj done
2016-06-12 15:39:40.658 TestRuntime[5571:415858] Thread2,unlock done
2016-06-12 15:39:40.658 TestRuntime[5571:415857] Thread1,wait done
2016-06-12 15:39:40.658 TestRuntime[5571:415857] Thread1,unlock done
說明,thread1在lock之后,執行了wait,然后會暫停執行,隨后thread2獲取到線程操作權;
知道thread2 執行了signal,thread1才會停止wait,并且繼續往下執行~