背景
我们平时使用的NSMutableArray,在进行增删改查的时候,会出现数据异常的场景(关键是异常并不是必现的,不太好复现)
尝试复现场景
先执行以下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | self.muArray = [NSMutableArray new ]; dispatch _ async(dispatch _ get _ global _ queue( 0 , 0 ), ^{ for (int i = 0 ; i < 3000 ; i++) { [self.muArray addObject :@ (i)]; NSLog( @ "====[%d]" , (int)self.muArray.count); } }); dispatch _ async(dispatch _ get _ global _ queue( 0 , 0 ), ^{ for (int i = 0 ; i < 3000 ; i++) { [self.muArray addObject :@ ( 10000 +i)]; NSLog( @ "====[%d]" , (int)self.muArray.count); } }); |
运行代码,发现最后array的个数并不等于6000,多运行几次,发现每次的结果都不一样
创建线程安全的数组
1、通过NSLock锁实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | NSLock *lock = [NSLock new ]; self.muArray = [NSMutableArray new ]; dispatch _ async(dispatch _ get _ global _ queue( 0 , 0 ), ^{ for (int i = 0 ; i < 3000 ; i++) { [lock lock]; [self.muArray addObject :@ (i)]; NSLog( @ "====[%d]" , (int)self.muArray.count); [lock unlock]; } }); dispatch _ async(dispatch _ get _ global _ queue( 0 , 0 ), ^{ for (int i = 0 ; i < 3000 ; i++) { [lock lock]; [self.muArray addObject :@ (i)]; NSLog( @ "====[%d]" , (int)self.muArray.count); [lock unlock]; } }); |
2、通过串行队列实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | dispatch_queue_t serialQueue = dispatch_queue_create( "com.name.apple" , DISPATCH_QUEUE_SERIAL); self.muArray = [NSMutableArray new ]; dispatch_async(dispatch_get_global_queue( 0 , 0 ), ^{ for ( int i = 0 ; i < 3000 ; i++) { dispatch_async(serialQueue, ^{ [self.muArray addObject:@(i)]; NSLog(@ "====[%d]" , ( int )self.muArray.count); }); } }); dispatch_async(dispatch_get_global_queue( 0 , 0 ), ^{ for ( int i = 0 ; i < 3000 ; i++) { dispatch_async(serialQueue, ^{ [self.muArray addObject:@(i)]; NSLog(@ "====[%d]" , ( int )self.muArray.count); }); } }); |