美文网首页
线程安全

线程安全

作者: xiari1991 | 来源:发表于2018-02-07 17:01 被阅读9次

一直不知道为什么线程会不安全,今天遇到了一种情况。

dispatch_queue_t queue = dispatch_queue_create("qcdSafe.test", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        for (int i =1000000; i< 2000000; i++) {
            if (self.arr.count < 900000) {
                [self.arr addObject:@(i)];
            }
        }
    });
    dispatch_async(queue, ^{
        for (int i =0; i< 1000000; i++) {
            if (self.arr.count < 900000) {
                [self.arr addObject:@(i)];
            }
        }
    });

多线程同时操作数组会发生闪退。
可以这样理解:如果修改数据发生在 同一个时刻,那么程序就不知改怎么处理数据了。这时会发生闪退。
而我们不单单要考虑是否发生闪退,还有考虑这个数组的大小是不是会超过900000。其实会超过的,这就是线程不安全的。

为什么要线程安全:比如我服务器有一个文件,10000个如何这个时候同时去修改这个文件,那么最终会怎么样呢?服务器也不知道,所以可能会闪退(ios nsfilemanager 是线程安全的,这里只是举例)。

那么怎么保证数组操作线程安全。我们讨论下NSLock

下面有三种方式,依次讨论

NSLock *lock = [[NSLock alloc] init];
    
    self.arr = [NSMutableArray array];
    
    dispatch_queue_t queue = dispatch_queue_create("qcdSafe.test", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        int j = 0;
        [lock lock];
        for (int i =1000000; i< 2000000; i++) {
            if (self.arr.count < 900000) {
                [self.arr addObject:@(i)];
                j++;
            }
        }
        [lock unlock];
        NSLog(@"count:%zd j=%d",self.arr.count, j);
    });
    dispatch_async(queue, ^{
        int w = 0;
        [lock lock];
        for (int i =0; i< 1000000; i++) {
            if (self.arr.count < 900000) {
                [self.arr addObject:@(i)];
                w++;
            }
        }
        [lock unlock];
        NSLog(@"count:%zd w=%d",self.arr.count, w);
    });

这种方式可以实现线程安全,但是添加数据只是在第一个线程中执行,第二个线程不会执行。因为lock会阻塞第二个线程,第一个线程lock时,第二个线程lock无效。只有当unlock时第二个线程才会执行,但数组的容量已经达到上限了。


NSLock *lock = [[NSLock alloc] init];
    
    self.arr = [NSMutableArray array];
    
    dispatch_queue_t queue = dispatch_queue_create("qcdSafe.test", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        for (int i =0; i< 1000000; i++) {
            if (self.arr.count < 900000) {
                [lock lock];
                [self.arr addObject:@(i)];
                [lock unlock];
            }
        }
        NSLog(@"count:%zd",self.arr.count);
    });
    dispatch_async(queue, ^{
        for (int i = 1000000; i< 2000000; i++) {
            if (self.arr.count < 900000) {
                [lock lock];
                [self.arr addObject:@(i)];
                [lock unlock];
            }
//            NSLog(@"2");
        }
        NSLog(@"count:%zd",self.arr.count);
    });

无法达到线程安全,数组容量可能超过900000。因为当两个线程同时到lock的时候,加入这个时候容量已经达到了900000-1.未阻塞的线程会添加一个元素到数组,unlock后,另一个线程还是会添加一个元素到数组中。

NSLock *lock = [[NSLock alloc] init];
        
        self.arr = [NSMutableArray array];
        
        dispatch_queue_t queue = dispatch_queue_create("qcdSafe.test", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(queue, ^{
            int i, w;
            w = 0;
            for (i = 0; i< 1000000; i++) {
                [lock lock];
                if (self.arr.count < 900000) {
                    [self.arr addObject:@(i)];
                    w++;
                }
                [lock unlock];
            }
            NSLog(@"count:%zd, w = %d",self.arr.count, w);
        });
        dispatch_async(queue, ^{
            int i,j;
            j = 0;
            for (i = 1000000; i< 2000000; i++) {
                [lock lock];
                if (self.arr.count < 900000) {
                    [self.arr addObject:@(i)];
                    j++;
                }
                [lock unlock];
            }
            NSLog(@"count:%zd, j = %d",self.arr.count, j);
        });

线程安全。

相关文章

  • atomic & nonatomic

    什么是线程安全??? 线程安全:多线程操作共享数据不会出现想不到的结果就是线程安全的,否则,是线程不安全的。 at...

  • ConcurrentHashMap源码设计分析

    二、线程安全(Thread-safe)的集合对象:● Vector 线程安全● HashTable 线程安全● S...

  • HashMap 和 Hashtable 的区别

    线程安全: HashMap 是非线程安全的,而 Hashtable 是线程安全的,因为 Hashtable 内部的...

  • Java 的 StringBuffer 和 StringBuil

    区别就是:线程安全,StringBuffer 是线程安全的,StringBuilder 不是线程安全的。 他俩的实...

  • Java单例模式,线程安全

    懒汉式:线程安全,开销大 双重检查锁:线程安全,根据需求使用 静态内部类锁:线程安全,比较推荐 饿汗式:线程安全,...

  • 2018-06-12 第三十七天

    一、线程安全 线程安全的问题,是针对多线程的程序。单线程的情况下,是不存在线程安全问题。 产生线程安全问题的原因:...

  • 线程安全知多少

    1. 如何定义线程安全 线程安全,拆开来看: 线程:指多线程的应用场景下。 安全:指数据安全。 多线程就不用过多介...

  • JAVA 线程安全

    线程安全定义 一个类在可以被多个线程安全调用时就是线程安全的。 线程安全分类 线程安全不是一个非真即假的命题,可以...

  • synchronized锁

    一、线程安全的概念与synchronized 1、线程安全概念 并发程序开发的一大关注重点就是线程安全,线程安全就...

  • 线程安全的NSMutableDictionary

    NSDictionary是线程安全的,NSMutableDictionary是线程不安全的。利用锁来保证线程的安全...

网友评论

      本文标题:线程安全

      本文链接:https://www.haomeiwen.com/subject/etlazxtx.html