zoukankan      html  css  js  c++  java
  • 多线程(二) 线程的安全隐患

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

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

    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,它是一个互斥锁,锁的概念将在下一篇中详细讲解

  • 相关阅读:
    python os
    [BZOJ2887] 旅行
    UVA1104 Chips Challenge
    CF364E Empty Rectangles
    CF1408H Rainbow Triples
    CF1214G Feeling Good
    CF506E Mr. Kitayuta's Gift
    采用Canal监听mysql数据库变化
    Java8 ParallelStream
    Java8 方法引用
  • 原文地址:https://www.cnblogs.com/luoxiaofu/p/5250145.html
Copyright © 2011-2022 走看看