iOS 多线程安全之产生原因
来源:互联网 发布:sai软件入门教程 编辑:程序博客网 时间:2024/05/22 15:08
在 iOS 中我们经常需要使用到 多线程 ,那么多线程 使用中有个问题 需要注意就是 多线程访问数据的安全。我们举例说明
现在 controller 中有两个属性。 对每个属性 我们分别使3个多线程 去读写 这两个属性
/*
nonatomic setter 和 getter 都不加锁
*/
@property (nonatomic,assign)NSInteger leftTicketsCount;
/**
使用atomic多线程原子性控制,atomic的原理给setter加上锁,getter不会加锁
*/
@property (atomic,assign)NSInteger newLefTicketsCount;
代码如下
#pragma mark ---- Thread fighting over shampo
/**
多线程争抢 资源 atomic 所谓争抢 就是几乎 同时访问的意思
*/
- (void)fightingOverShampo
{
self.leftTicketsCount=10;
//开启多个线程,模拟售票员售票
self.thread1=[[NSThreadalloc]initWithTarget:selfselector:@selector(sellTickets)object:nil];
self.thread1.name=@"售票员1";
self.thread2=[[NSThreadalloc]initWithTarget:selfselector:@selector(sellTickets)object:nil];
self.thread2.name=@"售票员2";
self.thread3=[[NSThreadalloc]initWithTarget:selfselector:@selector(sellTickets)object:nil];
self.thread3.name=@"售票员3";
[self.thread1start];
[self.thread2start];
[self.thread3start];
}
- (void)sellTickets
{
while (true) {
// 从代码来看应该应该不可能出现 负数的票数
// NSLog(@"start ticket %ld---",(long)self.leftTicketsCount);
if (self.leftTicketsCount>0) {// 读取
NSLog(@"valid ticke %ld",self.leftTicketsCount);
[NSThreadsleepForTimeInterval:1]; //这句话 是关键睡眠 执行笔者认为 如果
self.leftTicketsCount--;
NSLog(@"thread:%@ ----> %ld",[[NSThreadcurrentThread] name],self.leftTicketsCount);
}else{
NSLog(@"break thread:%@ ----> %ld",[[NSThreadcurrentThread] name],self.leftTicketsCount);
break;
}
}
}
#pragma mark ---- 第二个 属性 对比
- (void)fightingOverShampoTwo
{
self.newLefTicketsCount=10;
//开启多个线程,模拟售票员售票
self.thread4=[[NSThreadalloc]initWithTarget:selfselector:@selector(atomicSellTicket)object:nil];
self.thread4.name=@"售票员4";
self.thread5=[[NSThreadalloc]initWithTarget:selfselector:@selector(atomicSellTicket)object:nil];
self.thread5.name=@"售票员5";
self.thread6=[[NSThreadalloc]initWithTarget:selfselector:@selector(atomicSellTicket)object:nil];
self.thread6.name=@"售票员6";
[self.thread4start];
[self.thread5start];
[self.thread6start];
}
- (void)atomicSellTicket
{
while (true) {
// 从代码来看应该应该不可能出现 负数的票数
// NSLog(@"start ticket %ld---",(long)self.leftTicketsCount);
if (self.newLefTicketsCount>0) {// 读取
// NSLog(@"valid ticke %ld",self.newLefTicketsCount);
[NSThreadsleepForTimeInterval:1]; //这句话 是关键睡眠 执行笔者认为 如果
self.newLefTicketsCount--;
NSLog(@"new thread:%@ ----> %ld",[[NSThreadcurrentThread] name],self.newLefTicketsCount);
}else{
// NSLog(@"break thread:%@ ----> %ld",[[NSThread currentThread] name],self.leftTicketsCount);
break;
}
}
}
结果若下:
我们发现 居然出现了 票数 为 负数的情况!!!!!
如果我们把 [NSThreadsleepForTimeInterval:1]; 这句话去掉 再次运行 就不会必然出现这种情况了。
这句话的作用是 我们人为的造成 争抢资源就是 多线程 同时访问 某个变量的 场景 。就好像大家都在同时按键盘抢票。 这个时候 数据是不正常的。不论我们 设置 属性是 atomic 还是 nonatomic 都会出现。
再次 假设 我们把 [NSThread sleepForTimeInterval:1] 替换上一个 耗时的代码 比如:
for (int i=0; i<1000;i++ ) {
for (int j=0; j<1000; j++) {
m++;
}
}
依然 出现 票数为 负数的情况 。 在多线程编程中, 很多开发者 很容易编写这样消耗时间的操作,过后很容易出现 数据 不正常的情况。
- iOS 多线程安全之产生原因
- iOS多线程之线程安全
- 多线程安全问题产生的原因
- Java 多线程产生的原因
- iOS开发:多线程之线程安全
- iOS多线程之线程安全和GCD
- 多线程(一):多线程问题产生原因
- Java 多线程:多线程产生的原因
- Java 多线程:多线程产生的原因
- namenode安全模式产生原因及作用
- 多线程访问HashpMap产生死锁原因
- 多线程死锁的产生原因及避免
- ios多线程 -- 线程安全
- iOS多线程安全详解
- iOS 多线程安全数组
- iOS 开发 多线程详解之线程安全(资源共享)
- [IOS 开发] CoreData多线程安全
- IOS 多线程(3) --线程安全
- zeppelin mysql配置
- 修复Bug,刷新无法动态显示数据库内容
- Qt调用系统动态链接库(系统API)
- smarty 配置问题
- PullToRefreshListView
- iOS 多线程安全之产生原因
- AtCoder:11(数论 & 思维)
- Qt 中有两种方式编译MinGW和MSVC
- cocoaPod新手安装+必须升级Ruby环境
- 面向对象的软件工程
- Mysql的事务
- C++初探
- 自旋锁,信号量,互斥量
- linux-系统基本结构