多线程线程资源共享问题
来源:互联网 发布:淘宝上的面膜是正品吗 编辑:程序博客网 时间:2024/06/11 19:12
简介
在多线程的环境下, 由于公共资源可能会被多个线程共享, 也就是多个线程可能会操作( 增、删、改等 )同一资源.
当多个线程操作同一块资源时, 很容易导致数据错乱或发生数据安全问题, 即:
数据有可能丢失, 有可能增加, 有可能错乱.
资源共享经典问题–>卖票
- 逻辑伪代码:
- if( 余票 > 0 )
……余票-1
else
……提示无票
代码
Swift
var votes = 10override func viewDidLoad() { super.viewDidLoad() // 售票 self.saleTickets()}@objc func saleTickets() { while true { // 模拟耗时操作 Thread.sleep(forTimeInterval: 1.0) if(self.votes > 0) { self.votes = self.votes - 1 print(Thread.current.description + " 余票数为 " + self.votes.description) } else { print(Thread.current.description + " 无票") break; } }}
OC
// 票数@property (nonatomic, assign) int votes;- (void)viewDidLoad { [super viewDidLoad]; self.tickets = 10; // 售票 [self saleTickets];}- (void)saleTickets{ while(YES) { // 模拟耗时操作 [NSThread sleepForTimeInterval:1.0]; if(self.votes > 0) { self.votes--; NSLog(@"余票数为%d", self.votes); } else { NSLog(@"无票"); break; } }}
问题
这时候我们在单线程上面运行是没问题的, 但是当有多个售票员(子线程)在卖票(共同访问同一个数据)的时候, 就会出现以下的情况:
代码:
OC
// 售票员1NSThread *conductor1 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTickets) object:nil];conductor1.name = @"售票员1";[conductor1 start];// 售票员2NSThread *conductor2 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTickets) object:nil];conductor2.name = @"售票员2";[conductor2 start];
Swift
// 售票员1let conductor1 = Thread.init(target: self, selector: #selector(saleTickets), object: nil)conductor1.name = "售票员1"conductor1.start()// 售票员2let conductor2 = Thread.init(target: self, selector: #selector(saleTickets), object: nil)conductor2.name = "售票员2"conductor2.start()
打印:
PS: 笔者记得两三年前刚接触iOS的多线程的时候, 测试有次测得余票数是-1的, 现在侧很久都没发现有-1的情况. 有兴趣的大兄弟可以试试
原因
解决
在共同资源( 票数 )被访问( 确切说是准备变化 )的时候( 如上图线程1写入时 ), 该资源只能被一个线程操作.
这时, 我们就可以使用互斥锁等保证被锁定的代码( 资源 ), 同一时间, 只能有一个线程可以操作.
代码修改:
Swift
@objc func saleTickets() { while true { Thread.sleep(forTimeInterval: 0.1) /// 添加互斥锁 /// 由于互斥锁为了数据安全会牺牲性能, 所有互斥锁的范围一定要尽可能地小 /// 参数: 可以使任意的继承自基类NSObject的对象 /// 但是, 这个参数一定要确保, 互斥的其他线程认识这把锁. /// 由于self本身就是一个全局变量, 所以一般我们都直接给self objc_sync_enter(self) if(self.votes > 0) { self.votes = self.votes - 1 print(Thread.current.description + " 余票数为 " + self.votes.description) } else { print(Thread.current.description + " 无票, 当前票数为" + self.votes.description) break; } objc_sync_exit(self) // 记得退出互斥锁 }}
OC
- (void)saleTickets{ while(YES) { // 模拟耗时操作 [NSThread sleepForTimeInterval:1.0]; // 添加互斥锁 @synchronized (self) { if(self.votes > 0) { self.votes--; NSLog(@"余票数为%d", self.votes); } else { NSLog(@"无票"); break; } } }}
阅读全文
0 0
- 多线程线程资源共享问题
- 多线程资源共享的问题
- 多线程资源共享
- 多线程资源共享
- Python中线程资源共享的问题
- iOS 开发 多线程详解之线程安全(资源共享)
- iOS多线程 - NSThread锁的使用(多线程资源共享的问题)
- 资源共享问题
- 多线程实现资源共享的问题学习与总结
- 多线程实现资源共享的问题学习与总结
- 多线程Thread类和Runnable接口资源共享问题分析
- Java 多线程之 Runnable VS Thread 及其资源共享问题
- 如何解决java线程中的资源共享的问题
- java回忆录(3)—ThreadLocal解决线程资源共享问题
- 【java】实现多线程资源共享
- 多线程实现资源共享
- 线程资源共享3
- 多线程-线程同步问题
- JavaScript
- 洛谷1216 数字三角形
- Batch normalization
- redis4.0.2集群配置
- jQuery的each函数
- 多线程线程资源共享问题
- 闭包选项卡
- vim配置文件
- 正则表达式的使用
- pug--HTML模板引擎安装编译
- 画一条虚线
- JAVA 对象引用,以及对象赋值(转,侵私立删)
- ZK 4G常见问题分析及处理(可用于有移动网络模块的设备)
- linux下yum升级git