synchronized
synchronized是對p_thread_mutex的封裝,也能對線程進行加鎖,從而實現(xiàn)線程同步。
看代碼:
[[[NSThread alloc] initWithTarget:self selector:@selector(thread1) object:nil] start];
[[[NSThread alloc] initWithTarget:self selector:@selector(thread2) object:nil] start];
- (void)thread1{
@synchronized (self) {
NSLog(@"%s", __func__);
}
}
- (void)thread2{
@synchronized (self) {
NSLog(@"%s", __func__);
}
}
最后能保證thread1方法在thread2方法之前執(zhí)行。一個對象對應一把鎖。synchronized使用起來相對方便,但由于它封裝的較多,所以性能并不是很好。
為什么要獲取某個對象?
傳入nil不起作用。
傳入的object的內(nèi)存地址作為key,通過hash map對應的一個系統(tǒng)維護的遞歸鎖。
傳入self容易導致死鎖。
//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生成同一把鎖,兩個公共鎖交替使用容易出現(xiàn)死鎖,正確的做法是傳入一個類內(nèi)部維護的NSObject對象,而且這個對象是外部不可見的。(引用自該篇文章:http://www.itdecent.cn/p/2dc347464188)
dispatch_semaphore_t
dispatch_semaphore_t也能實現(xiàn)線程同步。
看代碼:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.semaphore = dispatch_semaphore_create(1);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
for (NSInteger i = 0; i < 10; i ++) {
dispatch_async(queue, ^{
[self test];
});
}
}
- (void)test{
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"begin。。。");
sleep(3);
NSLog(@"test:%@", [NSThread currentThread]);
dispatch_semaphore_signal(self.semaphore);
}
在創(chuàng)建semaphore的時候,初始參數(shù)為1就能保證線程的同步。其中的參數(shù)是指線程最大并發(fā)數(shù)。那么我們也就可以利用GCD中的semaphore設置線程的最大并發(fā)數(shù)了。
這里還有semaphore異步變同步的用法
iOS開發(fā)中GCD的一些用法