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

  • 相关阅读:
    Queryable.Union 方法实现json格式的字符串合并
    战舰少女官方网站正式开启 -手机卡牌游戏
    星工场逆转娱乐圈预计5.1后上线
    Eclipse编辑jsp卡死解决方案
    Eclipse的workspace中放入Ext JS卡死或OOM的解决方案
    Ext Js详解指南
    Android 自定义RadioButton实现
    反编译Android APK及防止APK程序被反编译
    Android自定义控件
    优秀博客
  • 原文地址:https://www.cnblogs.com/luoxiaofu/p/5250145.html
Copyright © 2011-2022 走看看