zoukankan      html  css  js  c++  java
  • ios多线程 -- 线程安全

    多线程的安全隐患

    资源共享
    一块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源.
    比如多个线程访问同一个对象、同一个变量、同一个文件.
    当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题.
    例如:一个售票系统中,多个线程同时读写剩余的票数,那么就会引起数据错乱.
    买票

    代码演示:

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @property (nonatomic, assign) int p;
    
    @property (nonatomic, strong) NSThread *thread1;
    @property (nonatomic, strong) NSThread *thread2;
    @property (nonatomic, strong) NSThread *thread3;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.p = 5;
    
        self.thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(download) object:nil];
        self.thread1.name = @"1号窗口";
        self.thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(download) object:nil];
        self.thread2.name = @"2号窗口";
        self.thread3 = [[NSThread alloc] initWithTarget:self selector:@selector(download) object:nil];
        self.thread3.name = @"3号窗口";
    
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        //启动线程
        [self.thread1 start];
        [self.thread2 start];
        [self.thread3 start];
    
    }
    
    - (void)download{
        while(1){
            //获取当前剩余票数
            int count = self.p;
            if (count > 0) {
                //暂停一段时间
                [NSThread sleepForTimeInterval:0.05];
                self.p = count - 1;
                NSLog(@"%@ 卖了一张票,剩余%d张票", [NSThread currentThread].name, self.p);
            }else{
                //退出线程
                [NSThread exit];
                return;
            }
        }
    }
    @end

    线程安全

    解决方案:

    IOS中解决线程安全的方法是用互斥锁机制 : @synchronized(obj) {}
    obj表示要加锁的对象(唯一的),最好是成员变量 或者 是self(最常用)
    注意:锁定的代码只能用一把锁,用多了锁是无效的.

    互斥锁的优缺点
    优点:能有效防止因多线程抢夺资源造成的数据安全问题
    缺点:需要消耗大量的CPU资源

    互斥锁的使用前提:多条线程抢夺同一块资源
    相关专业术语:怎么解决线程同步问题? 用互斥锁机制(@synchronized)
    线程同步的意思是:多条线程在同一条线上执行(按顺序地执行)
    互斥锁,就是使用了线程同步技术

    上述代码的download方法改为:

    - (void)download{
        while (1) {
            @synchronized(self) {//互斥锁,解决线程同步问题
                int count = self.p;
                if (count > 0) {
                    [NSThread sleepForTimeInterval:0.05];
                    self.p = count - 1;
                    NSLog(@"%@卖了一张票,剩余%d张票", [NSThread currentThread].name, self.p);
                }else{
                    //退出线程
                    [NSThread exit];
                    return;
                }
            }
    
        }
    }

    线程安全

    分析:
    未加锁前
    未加锁
    加锁后:
    加锁后

    补充:原子和非原子属性

    OC在定义属性时有 nonatomic 和 atomic 两种选择
    atomic:原子属性,为setter方法加锁(默认就是atomic)
    nonatomic:非原子属性,不会为setter方法加锁(常用)

    (1) 非ARC下(MRC), nonatomic生成的 getter 和setter 方法

    @property (retain, nonatomic) NSArray foods;
    - (void)setFoods:(NSArray *)foods
    {
        if (_foods != foods) {
            [_foods release];
            _foods = [foods retain];
    
            // do something
        }
    }
    - (NSArray *)foods
    {
        return _foods;
    }

    (2) 非ARC下(MRC), atomic生成的 getter 和setter 方法

    @property (retain, atomic) NSArray foods;
    - (void)setFoods:(NSArray *)foods
    {
        @synchronized(self) {
        if (_foods != foods) {
            [_foods release];//旧值释放
            _foods = [foods retain];//持有新值
    
            // do something
            }
        }
    }
    
    - (NSArray *)foods
    {
        @synchronized(self) {
            return _foods;
        }
    }

    原子和非原子属性的选择: nonatomic 和 atomic 对比
    atomic:线程安全,需要消耗大量的资源(一般用于 Mac 开发)
    nonatomic:非线程安全,适合内存小的移动设备(一般用于 IOS 开发)

    iOS开发的建议
    (1) 所有属性都声明为 nonatomic (节省内存消耗)
    (2) 尽量避免多线程抢夺同一块资源
    (3) 尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力

  • 相关阅读:
    基于摸板匹配的目標跟蹤算法
    spoj 2713 Can you answer these queries IV
    zoj 3633 Alice's present
    hdu 3642 Get The Treasury
    poj 1195 Mobile phones
    poj 2760 End of Windless Days
    zoj 3540 Adding New Machine
    spoj 1716 Can you answer these queries III
    spoj 1043 Can you answer these queries I
    spoj 2916 Can you answer these queries V
  • 原文地址:https://www.cnblogs.com/xiaocai-ios/p/7779778.html
Copyright © 2011-2022 走看看