多线程

科普 问题:线程不安全一定crash么? 线程不安全可能crash么?
答案: 不一定 ,可能
线程安全 就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能访问直到该线程读取完,其他线程才可使用,不会出现数据不一致或数据污染
线程不安全 就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据时脏数据
如果你的代码所在的进程中有多个线程同时运行,而这些线程可能同时运行这段代码,如果每次运行结果和单线程运行结果是一样的,而且其他变量的值也和预期是一样的,就是线程安全的
【多线程】线程安全问题都是由于全局变量和静态变量引起的
若每个线程对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能印象线程安全
参考链接:
https://blog.csdn.net/ghevinn/article/details/37764791

  • 数组线程不安全不crash eg
self.array = [NSMutableArray array]; self.arrayConcurrencyQueue = dispatch_queue_create("com.sohu.qq", DISPATCH_QUEUE_CONCURRENT); dispatch_queue_t queue = dispatch_queue_create("com.sohu.sync", DISPATCH_QUEUE_CONCURRENT); for ( int i =0; i < 100; i++) { dispatch_async(self.arrayConcurrencyQueue, ^{ //[self addObject:[NSNumber numberWithInteger:i]]; //[self printCount]; [self.array addObject:[NSNumber numberWithInteger:i]]; NSLog(@"dispatch_async self.arrayCount:%zd",self.array.count); }); }

执行结果不crash

多线程
文章图片
image.png
  • 非线程安全crash
self.array = [NSMutableArray array]; self.arrayConcurrencyQueue = dispatch_queue_create("com.sohu.qq", DISPATCH_QUEUE_CONCURRENT); dispatch_queue_t queue = dispatch_queue_create("com.sohu.sync", DISPATCH_QUEUE_CONCURRENT); for ( int i =0; i < 100; i++) { dispatch_async(self.arrayConcurrencyQueue, ^{ //[self addObject:[NSNumber numberWithInteger:i]]; //[self printCount]; [self.array insertObject:[NSNumber numberWithInteger:i] atIndex:i]; NSLog(@"dispatch_async self.arrayCount:%zd",self.array.count); }); } NSLog(@"for after self.arrayCount:%zd",self.array.count);

结果:

多线程
文章图片
image.png
  • 数组线程安全eg
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib.- () self.array = [NSMutableArray array]; self.arrayConcurrencyQueue = dispatch_queue_create("com.sohu.qq", DISPATCH_QUEUE_CONCURRENT); dispatch_queue_t queue = dispatch_queue_create("com.sohu.sync", DISPATCH_QUEUE_CONCURRENT); for ( int i =0; i < 100; i++) { dispatch_async(queue, ^{ [self addObject:[NSNumber numberWithInteger:i]]; [self printCount]; }); } NSLog(@"for after self.arrayCount:%zd",self.array.count); //TODO 小结 引发对线程安全的理解线程安全定义重新查看线程安全 != Crash }- (void)addObject:(id)object{ dispatch_barrier_async(self.arrayConcurrencyQueue, ^{ [self.array addObject:object]; }); }- (void)printCount{ dispatch_async(self.arrayConcurrencyQueue, ^{ NSLog(@"dispatch_async self.arrayCount:%zd",self.array.count); }); }

原理:

多线程
文章图片
image.png 扩展:写一个线程安全的NSMutableArray子类,未完待续
问题:
1、
__block int a= 0; //1 while (a < 10) { dispatch_async(dispatch_get_global_queue(0, 0), ^{ a++; NSLog(@"%@---%d",[NSThread currentThread],a); }); NSLog(@"while-after:%@---%d",[NSThread currentThread],a); } NSLog(@"终于等到你:%d",a);

2dispatch_get_main 官方注释理解main函数的关系 与runLoop 自动释放池的关系 3 、创建线程安全的可变数组



4、 多线程
文章图片
image.png
给出答案
5、栅栏函数不能用系统的globalQueue
6、为啥画UI要在主线程 离屏渲染
7、
for ( int i = 0; i < 100; i++) {
dispatch_async(self.arrayConcurrencyQueue, ^{
// [self addObject:[NSNumber numberWithInteger:i]];
// [self printCount];
@synchronized (self) {
[self.array addObject:[NSNumber numberWithInteger:i]];
}
NSLog(@"dispatch_async self.arrayCount:%zd",self.array.count); }); }

以上代码,为啥同步锁不起作用?换成 self.lock = [[NSLock alloc] init]; 依然不起作用为啥?

    推荐阅读