美文网首页
互斥锁和自旋锁

互斥锁和自旋锁

作者: ImmortalSummer | 来源:发表于2019-08-13 10:56 被阅读0次

    当多个线程访问同一个变量时, 很容易引发数据安全问题. 可以添加 互斥锁或者自旋锁解决这个问题.

    自旋锁
    当一个线程获取这个锁以后, 其他线程会抑制循环在哪里查看该锁是否被释放, 该锁不适合用于锁定保持时间过长的情况, 且消耗较大的性能.

    互斥锁
    当一个线程获得这个锁以后, 其他线程会被阻塞, 知道该锁被释放.

    原子属性
    atmoic/nonatmoic

    atmoic:原子属性,为系统默认的属性,会为修饰的成员变量的setter方法自动加锁(自旋锁),使得线程安全,但较为消耗资源,效率相对低些。是一种单写多度的多线程技术,可能出现脏数据。

    nonatomic:非原子属性,开发中最常用的属性,不会为修饰的成员变量的setter方法加锁,虽然线程不安全,但效率高.

    互斥锁示例:

    @interface ViewController (){
        int index;
    }
    
    //...
    
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [self testLock:@"a"];
        });
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [self testLock:@"b"];
        });
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [self testLock:@"c"];
        });
    }
    
    -(void)testLock:(NSString *)flag{
        NSLog(@"flag:%@ 当前线程:%@",flag,[NSThread currentThread]);
        
        @synchronized (@"token") {
            for (int i=0; i<3; i++) {
                index++;
                sleep(0.1);
                NSLog(@"flag:%@ %d", flag, index);
            };
        }
    }
    
    -(void)testUnlock:(NSString *)flag{
        NSLog(@"flag:%@ 当前线程:%@",flag,[NSThread currentThread]);
        
        for (int i=0; i<3; i++) {
            index++;
            sleep(0.1);
            NSLog(@"flag:%@ %d", flag, index);
        };
    }
    
    /* 加锁 testLock 运行结果
    2019-08-13 10:55:32.382984+0800 自旋锁和互斥锁[96408:4773768] flag:c 当前线程:<NSThread: 0x600002a7c600>{number = 5, name = (null)}
    2019-08-13 10:55:32.383005+0800 自旋锁和互斥锁[96408:4773766] flag:a 当前线程:<NSThread: 0x600002a2be80>{number = 3, name = (null)}
    2019-08-13 10:55:32.383020+0800 自旋锁和互斥锁[96408:4773769] flag:b 当前线程:<NSThread: 0x600002a07f40>{number = 4, name = (null)}
    2019-08-13 10:55:32.383308+0800 自旋锁和互斥锁[96408:4773768] flag:c 1
    2019-08-13 10:55:32.383444+0800 自旋锁和互斥锁[96408:4773768] flag:c 2
    2019-08-13 10:55:32.383612+0800 自旋锁和互斥锁[96408:4773768] flag:c 3
    2019-08-13 10:55:32.383771+0800 自旋锁和互斥锁[96408:4773769] flag:b 4
    2019-08-13 10:55:32.383909+0800 自旋锁和互斥锁[96408:4773769] flag:b 5
    2019-08-13 10:55:32.384102+0800 自旋锁和互斥锁[96408:4773769] flag:b 6
    2019-08-13 10:55:32.384352+0800 自旋锁和互斥锁[96408:4773766] flag:a 7
    2019-08-13 10:55:32.384701+0800 自旋锁和互斥锁[96408:4773766] flag:a 8
    2019-08-13 10:55:32.385032+0800 自旋锁和互斥锁[96408:4773766] flag:a 9
    */
    /* 不加锁 testUnlock 运行结果
    2019-08-13 10:55:58.147531+0800 自旋锁和互斥锁[96415:4774371] flag:c 当前线程:<NSThread: 0x6000022b7940>{number = 4, name = (null)}
    2019-08-13 10:55:58.147584+0800 自旋锁和互斥锁[96415:4774370] flag:b 当前线程:<NSThread: 0x6000022943c0>{number = 5, name = (null)}
    2019-08-13 10:55:58.147586+0800 自旋锁和互斥锁[96415:4774372] flag:a 当前线程:<NSThread: 0x600002290380>{number = 3, name = (null)}
    2019-08-13 10:55:58.147786+0800 自旋锁和互斥锁[96415:4774372] flag:a 3
    2019-08-13 10:55:58.147786+0800 自旋锁和互斥锁[96415:4774370] flag:b 3
    2019-08-13 10:55:58.147787+0800 自旋锁和互斥锁[96415:4774371] flag:c 3
    2019-08-13 10:55:58.147914+0800 自旋锁和互斥锁[96415:4774372] flag:a 4
    2019-08-13 10:55:58.147953+0800 自旋锁和互斥锁[96415:4774370] flag:b 5
    2019-08-13 10:55:58.147986+0800 自旋锁和互斥锁[96415:4774371] flag:c 6
    2019-08-13 10:55:58.148256+0800 自旋锁和互斥锁[96415:4774372] flag:a 7
    2019-08-13 10:55:58.148509+0800 自旋锁和互斥锁[96415:4774371] flag:c 8
    2019-08-13 10:55:58.149224+0800 自旋锁和互斥锁[96415:4774370] flag:b 9
    */
    

    NSLock

    @interface ViewController (){
        NSLock *lock;
    }
    
    -(void)testNSLock:(NSString *)flag{
        NSLog(@"flag:%@ 当前线程:%@",flag,[NSThread currentThread]);
        
        //多个线程要用同一个锁
        if (!lock) {
            lock = [NSLock new];
        }
        
        [lock lock];
        for (int i=0; i<3; i++) {
            index++;
            sleep(0.1);
            NSLog(@"flag:%@ %d", flag, index);
        };
        [lock unlock];
    }
    

    自旋锁示例:(失败的)

    #import <os/lock.h>
    
    os_unfair_lock_t unfairLock = &(OS_UNFAIR_LOCK_INIT);
    os_unfair_lock_lock(unfairLock);
    //lock coding 要加锁的代码
    os_unfair_lock_unlock(unfairLock);
    
    #import <libkern/OSAtomic.h>
    
    OSSpinLock lock = OS_SPINLOCK_INIT;
    OSSpinLockLock(&lock);
    //lock coding 要加锁的代码
    OSSpinLockUnlock(&lock);
    
    //OSSpinLock ios10开始过期了
    

    自旋锁搞了搞几次都不成, 反正性能也不好, 不用了哈哈哈

    相关文章

      网友评论

          本文标题:互斥锁和自旋锁

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