多线程 线程的安全隐患

Posted 罗小浮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程 线程的安全隐患相关的知识,希望对你有一定的参考价值。

有了多线程就有了资源竞争,当多个线程对同一资源进行操作时就容易出现安全隐患。

下面举一个卖票的例子来说明线程的安全隐患

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@interface ViewController ()
 
@property (assign, nonatomic)NSInteger tickets;
 
@end
 
@implementation ViewController
 
- (void)viewDidLoad {
    [super viewDidLoad];
    //设置票的数量为5
    _tickets = 5;
    //线程一
    NSThread *threadOne = [[NSThread alloc] initWithTarget:self selector:@selector(saleTickets) object:nil];
    threadOne.name = @"threadOne";
    //线程二
    NSThread *threadTwo = [[NSThread alloc] initWithTarget:self selector:@selector(saleTickets) object:nil];
     
    //开启线程
    [threadOne start];
    [threadTwo start];
     
}
 
- (void)saleTickets
{
    while (1)
    {
        [NSThread sleepForTimeInterval:1];
        if (_tickets > 0)
        {
            _tickets--;
            NSLog(@"剩余票数= %ld",_tickets);
        }
        else
        {
            NSLog(@"票卖完了");
            break;
        }
    }
    
}

 打印结果技术分享

可以看到票的余量是很混乱的,看下面一张图可以比较清楚的了解为什么会出现这种情况

技术分享

 

如何解决?添加互斥锁(当A线程对数据进行操作时(加锁),线程B不能访问当前数据,直到A对数据完成读写操作结束(解锁),线程B才能对数据进行操作)

这样就保证了数据的安全性;

    下面是代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@interface ViewController ()
 
@property (assign, nonatomic)NSInteger tickets;
 
@end
 
@implementation ViewController
 
- (void)viewDidLoad {
    [super viewDidLoad];
    //设置票的数量为5
    _tickets = 5;
    //线程一
    NSThread *threadOne = [[NSThread alloc] initWithTarget:self selector:@selector(saleTickets) object:nil];
    threadOne.name = @"threadOne";
    //线程二
    NSThread *threadTwo = [[NSThread alloc] initWithTarget:self selector:@selector(saleTickets) object:nil];
     
    //开启线程
    [threadOne start];
    [threadTwo start];
     
}
 
- (void)saleTickets
{
    while (1)
    {
        @synchronized(self) {
            [NSThread sleepForTimeInterval:1];
            if (_tickets > 0)
            {
                _tickets--;
                NSLog(@"剩余票数= %ld",_tickets);
            }
            else
            {
                NSLog(@"票卖完了");
                break;
            }
        }
    }
    
}

 打印结果,可以看到数据正常了;

技术分享

关于代码中用到的@synchronized,它是一个互斥锁,锁的概念将在下一篇中详细讲解

以上是关于多线程 线程的安全隐患的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 互斥锁&&自旋锁 多线程安全隐患(转载)

简单的多线程买票模拟程序(lock解决多线程存在大安全隐患)

单例设计模式---懒汉式的多线程安全隐患

JAVA多线程安全

iOS开发多线程篇—线程安全

iOS开发多线程篇 03 —线程安全