科普
问题:线程不安全一定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
- 非线程安全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);
结果:
- 数组线程安全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);
});
}
原理:
扩展:写一个线程安全的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);
2 dispatch_get_main 官方注释理解 main函数的关系 与runLoop 自动释放池的关系
3 、创建线程安全的可变数组
4、给出答案
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];依然不起作用为啥?