多线程的安全隐患,及解决方法

Posted on 2016-07-16 18:39  柠檬片  阅读(119)  评论(0)    收藏  举报
  • 安全隐患:
    当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题.

  • 解决方法:

    使用互斥锁:

    互斥锁使用格式

    @synchronized(锁对象) { // 需要锁定的代码  }

    注意:锁定1份代码只用1把锁,用多把锁是无效的

 

  • 互斥锁的优缺点
  优点:能有效防止因多线程抢夺资源造成的数据安全问题
  缺点:需要消耗大量的CPU资源
  
  互斥锁的使用前提:多条线程抢夺同一块资源
  
  相关专业术语:线程同步
  线程同步的意思是:多条线程在同一条线上执行(按顺序地执行任务)
  互斥锁,就是使用了线程同步技术
 
  
 1 #import "ViewController.h"
 2 
 3 @interface ViewController ()
 4 //售票员01
 5 @property (nonatomic, strong) NSThread *thread01;
 6 //售票员02
 7 @property (nonatomic, strong) NSThread *thread02;
 8 //售票员03
 9 @property (nonatomic, strong) NSThread *thread03;
10 
11 //总票数
12 @property(nonatomic, assign) NSInteger totalticket;
13 
14 //@property (nonatomic, strong) NSObject *obj;
15 @end
16 
17 @implementation ViewController
18 
19 - (void)viewDidLoad {
20     [super viewDidLoad];
21 
22     //假设有100张票
23     self.totalticket = 100;
24 //    self.obj = [[NSObject alloc]init];
25     //创建线程
26    self.thread01 =  [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];
27     self.thread01.name = @"售票员01";
28     
29     self.thread02 =  [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];
30     self.thread02.name = @"售票员02";
31     self.thread03 =  [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];
32     self.thread03.name = @"售票员03";
33 }
34 
35 -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
36 {
37     //启动线程
38     [self.thread01 start];
39     [self.thread02 start];
40     [self.thread03 start];
41 }
42 
43 //售票
44 -(void)saleTicket
45 {
46     while (1) {
47        
48         //2.加互斥锁
49         @synchronized(self) {
50             [NSThread sleepForTimeInterval:0.03];
51             //1.先查看余票数量
52             NSInteger count = self.totalticket;
53             
54             if (count >0) {
55                 self.totalticket = count - 1;
56                 NSLog(@"%@卖出去了一张票,还剩下%zd张票",[NSThread currentThread].name,self.totalticket);
57             }else
58             {
59                 NSLog(@"%@发现当前票已经买完了--",[NSThread currentThread].name);
60                 break;
61             }
62         }
63     
64     }
65 
66 }
67 
68 
69 @end
示例