ObjC synchronize,GCD
- (NSString *)myString {
@synchronized(self) {
return [[myString retain] autorelease];
}
}
转换1:
- (NSString *)myString {
NSString *retval = nil;
pthread_mutex_t *self_mutex = LOOK_UP_MUTEX(self);
pthread_mutex_lock(self_mutex);
retval = [[myString retain] autorelease]; //Exception-Safe need
pthread_mutex_unlock(self_mutex);
return retval;
}
转换2:
// needs #import mm/mm-sync.h
- (NSString*) myString {
id retVal = nil;
mm_sync_enter(self);
@try {
retVal = [[myString retain] autorelease];
}
@catch(NSException* ex) {
}
@finaly {
mm_sync_exit(self);
}
return retVal;
}
更高效的是spin_lock,可以对需要并发共享的数据进行非常精细的控制。但如何做到异常安全,需要非常小心。
GCD
queue是任务存取的队列,FIFO。有两种类型的任务队列:并行和串行。
GCD只提供入队的api,即dispatch_[a]sync、dispatch_group_async、dispatch_barrier_async,出队的api由GCD library自己实现,大致的实现逻辑是这样的:在多个/单个线程中,循环出队,执行任务。
由于async在处理同步时较为复杂,GCD提供了dispatch_group_async、dispatch_barrier_async来完成异步任务的时序同步。
dispatch_barrier_async保证barrier之前的async task执行结束后,barrier之后的任务才开始执行:
dispatch_queue_t queue = dispatch_queue_create("me.xjump.concurrent_barrier", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"dispatch_async1");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:4];
NSLog(@"dispatch_async2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
[NSThread sleepForTimeInterval:4];
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"dispatch_async3");
});
group_async可以实现一批async task执行结束后,在notify回调中进行批任务完成处理:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"group1");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"group2");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"group3");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"updateUi");
});
dispatch_release(group);
避免在main线程中调用,但需要同步等待结果:
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
// check sema is nil??
dispatch_async(dispatch_get_global_queue(0, 0), ^{
@try {
result = [service callSomeMethod];
}
@catch (NSException *exception) {
NSLog(@"%@", exception.reason);
}
@finally {
dispatch_semaphore_signal(sema);
}
});
// dispatch_time( dispatch_time_t when, int64_t delta);
// dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, 1000*1000*3);
// dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
// dispatch_release(sema);
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(60.0 * NSEC_PER_SEC));
if(0==dispatch_semaphore_wait(sema, timeout)){
dispatch_release(sema);
}
在非main线程处理业务,处理结束后更新UI:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
// biz start ...
// bala bala
// biz end
dispatch_async(dispatch_get_main_queue(), ^(void){
// update UI
});
});
关于global queue的并发特性:
DISPATCH_QUEUE_PRIORITY_BACKGROUND:并行队列,任务会串行执行;
DISPATCH_QUEUE_PRIORITY_LOW:并行队列,任务会串行执行;
DISPATCH_QUEUE_PRIORITY_DEFAULT:并行队列,任务会串行执行;
DISPATCH_QUEUE_PRIORITY_HIGH:并行队列,任务会串行执行;
BACKGROUND, LOW, DEFAULT, HIGH 分别代表不同的优先级,高优先级队列中的任务会优先调度。
#define DISPATCH_QUEUE_PRIORITY_HIGH 2
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
#define DISPATCH_QUEUE_PRIORITY_LOW (-2)
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
而对于main queue来说,只能由main线程获取队列任务,然后进行调度执行,所以是串行的。
当main、global这两个任务队列不能满足要求时,还可以创建自定义的队列。
创建concurrent queue:
dispatch_queue_t q = dispatch_queue_create("me.xjump.concurrent_queue", DISPATCH_QUEUE_CONCURRENT);
创建serial queue:
dispatch_queue_t q = dispatch_queue_create("me.xjump.serial_queue", DISPATCH_QUEUE_SERIAL);
从GCD api手册上了看,有dispatch_get_global_queue,但没有获取自定义的queue的api,这个时候,可以使用Singleton和map来实现。
关于GCD,线程池实际上是共享的,看下图:

参考:
https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref
http://blog.csdn.net/totogo2010/article/details/8016129
http://stackoverflow.com/questions/16283652/understanding-dispatch-async
http://opensource.apple.com/source/mm4/mm4-437.1/runtime/mm-sync.m
http://www.kuro5hin.org/story/2011/1/21/193921/656