本文整理自《Effective Objective-C 2.0》,通过分析比较不同的同步锁的优缺点,使用GCD方法一步步找到更高效的同步锁。
在Objective-C中,如果有多个线程要执行同一份代码,那么这时就会出现线程安全问题。首先,我们看下什么时候线程安全问题。
线程安全
如果一段代码所在的进程中有多个线程在同时运行,那么这些线程就有可能会同时运行这段代码。假如多个线程每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
由于可读写的全局变量及静态变量(在 Objective-C 中还包括属性和实例变量)可以在不同线程修改,所以这两者也通常是引起线程安全问题的所在。
Objective-C中的同步锁
在 Objective-C 中,如果有多个线程执行同一份代码,那么有可能会出现线程安全问题。这种情况下,就需要使用所来实现某种同步机制。
在 GCD出现之前,有两种方法,一种采用的是内置的“同步块”(synchronization block),另一种方法是使用锁对象。
同步块(synchronization block)
- (void)synchronizedMethod {
@synchronized (self) {
//Safe
}
}
这种写法会根据给定的对象,自动创建一个锁,并等待块中的代码执行完毕。执行到这段代码结尾处,锁就释放了。
该同步方法的优点就是我们不需要在代码中显式的创建锁对象,便可以实现锁的机制。然而,滥用@synchronized (self)则会降低代码效率,因为公用同一个锁的那些同步块,都必须按顺序执行。若是在self对象上频繁加锁,程序可能要等另一段与此无关的代码执行完毕,才能继续执行当前代码,这样效率就低了。
注:因为@synchronized (self)方法针对self只有一个锁,相当于对于self的所有用到同步块的地方都是公用同一个锁,所以如果有多个同步块,则其他的同步块都要等待当前同步块执行完毕才能继续执行。
- (void)synchronizedAMethod {
@synchronized (self) {
//Safe
}
}
- (void)synchronizedBMethod {
@synchronized (self) {
//Safe
}
}
- (void)synchronizedCMethod {
@synchronized (self) {