线程安全的概念是,当多个线程同时访问一个资源时,要确保资源的准确性。也就是说,多个线程必须同步访问一块资源……
实现线程安全就是加锁。加锁,锁定的代码要尽量少。加锁范围内的代码,同一时间只允许一个线程执行。互斥锁@synchronized (self)的参数,任何继承NSObject的对象都可以,如:self。要保证这个锁对象,所有的线程都能访问到,而且所有线程访问的是同一个锁对象。
线程实现同步的两种锁:(互斥锁与自旋锁的概念在“区别”中有定义)
1,互斥锁
2,自旋锁
共同点:
能够锁定一段代码,同一时间,只有一个线程能够执行这段锁定的代码。
区别:
互斥锁:在锁定的时候,其他线程会进入睡眠状态,等待条件满足时,重新唤醒。(当A线程在线程池中,CUP进行处理时,其他线程会从线程池出来,进入睡眠状态,等待唤醒)
自旋锁:在锁定的时候,其他线程会进入一个死循环,也是一直在等待条件满足,一旦条件满足,立即执行,少了一个唤醒过程。(当A线程在线程池中,CPU进行处理时,其他线程还在线程池里面)
就因为自旋锁少了一个唤醒线程的过程,所以自旋锁的效率要比互斥锁高那么一点点。因此我们在锁定一段代码时,写@synchronized(self){}的时候,在Xcode中并不会有提示,原因是苹果不推荐加锁,加锁性能太差!
在定义属性时,如:@property(atomic, strong) NSObject *obj; 其关键字atomic为原子性,(默认的属性就为原子属性),原子性就是为多线程设计的,原子性实现单(线程)写多(线程)读。因为写的安全级别要求更高,读的要求低一些,可以多读几次确保数据的正确性。
在下面重写了setter和getter方法:如果同时重写了setter方法和getter方法,“_成员变量”就不会提供,就可以使用合成指令@synthesize,告诉编译器属性成员变量的名称:
@synthesize obj = _obj;
- (void)setObj:(NSObject *)obj
{
@synchronized (self){ //模拟锁。真实情况下,使用的不是互斥锁。原子属性内部使用的是自旋锁……
_obj = obj;
}
}
- (NSObject *)Obj
{
return _obj;
}
UI线程,我们一般可称为主线程。UIKit中绝大部分类,都不是“线程安全”的。怎么解决这个线程不安全的问题?苹果约定,所有程序更新UI都在主线程中进行,也就不会出现多个线程同时改变一个资源。
在主线程中更新UI,有什么好处?
1,在主线程中更新UI,就不会出现多个线程同时改变同一个UI控件。
2,主线程优先级最高,也就意味着UI的更新优先级高,让用户感觉运行很流畅。