多线程-锁

  • OSSpinLock
    1>自旋锁,等待锁的线程会处于忙等(busy-wait)状态,始终占着CPU资源;
    2>实现原理:相当于执行一个while循环;
    3>目前已经不再安全,可能出现优先级反转问题,如果等待锁的线程优先级比较高,它会一直占着CPU资源,优先级低的线程就无法解锁;

多线程实现:利用时间片调度算法
线程优先级:优先级高的线程分配的时间比较多,优先级低的线程分配的时间比较少

#import <libkern/OSAtomic.h>
    //初始化锁
    OSSpinLock lock = OS_SPINLOCK_INIT;
    
    //尝试加锁
    bool result = OSSpinLockTry(&lock);
    
    //加锁
    OSSpinLockLock(&lock);
    
    //解锁
    OSSpinLockUnlock(&lock);

  • os_unfair_lock
    1> iOS10开始取代不安全的OSSpinLock
    2> 从底层来看,等待os_unfair_lock锁的线程,处于休眠状态,而非忙等
#import <os/lock.h>

os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
os_unfair_lock_lock(&lock);
bool result = os_unfair_lock_trylock(&lock);
if(result)
{
    //code here
}
os_unfair_lock_unlock(&lock);

  • pthread_mutex_t
    1>互斥锁,等待锁的线程会处于 休眠状态
#import <pthread.h>
- (void)_init_pthread_mutex:(pthread_mutex_t *)mutex
{
    pthread_mutexattr_t mutexattr;
    pthread_mutexattr_init(&mutexattr);
    pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_DEFAULT);
    pthread_mutex_init(mutex, &mutexattr);
    pthread_mutexattr_destroy(&mutexattr);
}


- (instancetype)init
{
    self = [super init];
    if (self) {
        
        [self _init_pthread_mutex:&_lock];
    }
    return self;
}

- (void)sale_tickets
{
/*
    bool result = pthread_mutex_trylock(& _lock);
    if (result) {
        //code here
    }
*/
    pthread_mutex_lock(& _lock);
    //code here
    pthread_mutex_unlock(& _lock);
}


  • pthread_mutex_t 之RECURSIVE
#import <pthread.h>

@interface pthread_mutex_recursive_test ()

@property(nonatomic,assign)pthread_mutex_t mutex;

@end

@implementation pthread_mutex_recursive_test

- (void)_init_pthread_mutex:(pthread_mutex_t)mutex
{
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    
    pthread_mutex_init(&mutex, &attr);
    
    pthread_mutexattr_destroy(&attr);
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self _init_pthread_mutex:_mutex];
    }
    return  self;
}

- (void)test
{
    pthread_mutex_lock(&_mutex);
    
    static int count = 0;
    if (count < 10) {
        NSLog(@"%d,%s",count, __func__);
        count++;
        [self test];
    }

    
    pthread_mutex_unlock(&_mutex);
}

  • pthread_mutex_t 与pthread_cond_t
#import <pthread.h>
@interface pthread_mutex_cond_test ()

@property(nonatomic,assign)pthread_mutex_t mutex;
@property(nonatomic,assign)pthread_cond_t cond;
@property(nonatomic,strong)NSMutableArray *data;


@end

@implementation pthread_mutex_cond_test

- (void)_init_pthread_mutex:(pthread_mutex_t)mutex
{
   pthread_mutexattr_t attr;
   pthread_mutexattr_init(&attr);
   pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
   
   pthread_mutex_init(&mutex, &attr);
   
   
   pthread_cond_init(&_cond, NULL);
   
   pthread_mutexattr_destroy(&attr);
}


- (instancetype)init
{
   self = [super init];
   if (self) {
       [self _init_pthread_mutex:_mutex];
       self.data = [NSMutableArray array];
   }
   
   return self;

}

- (void)test
{
   [[[NSThread alloc] initWithBlock:^{
       
       pthread_mutex_lock(&self->_mutex);
       NSLog(@"__remove - begin");

       if (self.data.count == 0) {
           NSLog(@"数组中没有数据");
           pthread_cond_wait(&self->_cond, &self->_mutex);
       }
       
       [self.data removeLastObject];
       NSLog(@"删除了元素");

       pthread_mutex_unlock(&self->_mutex);
       
       }] start];
   
   
   [[[NSThread alloc] initWithBlock:^{
       
       pthread_mutex_lock(&self->_mutex);
       
       [self.data addObject:@"abc"];
       NSLog(@"添加了元素");

       pthread_mutex_unlock(&self->_mutex);
       pthread_cond_signal(&self->_cond);
       
       pthread_cond_broadcast(&self->_cond);

       
       }] start];

}

@end

  • dispatch_semaphore_t
    1> semaphore - 信号量
    2> 信号量的的初始值,可以控制线程并发访问的最大量
    3> 信号量的初始值为1,代表同时只允许1条线程访问资源,保证线程同步
@interface dispatch_semaphore_test ()

@property(nonatomic,strong)dispatch_semaphore_t semaphore;


@end

@implementation dispatch_semaphore_test

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.semaphore = dispatch_semaphore_create(3);
    }
    
    return self;
}


- (void)est
{
    for (int i = 0; i < 15; i++) {
        NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(_test) object:nil];
        [thread setName:[NSString stringWithFormat:@"子-%i",I]];
        [thread start];
    }
}

- (void)_test
{
    dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
    
    NSLog(@"%@",[NSThread currentThread]);
    sleep(2);
    dispatch_semaphore_signal(self.semaphore);
}

  • 串行队列
@interface dispatch_queue_serial_test ()
@property(nonatomic,strong)dispatch_queue_t queue;
@property(nonatomic,strong)dispatch_queue_t ticket_queue;
@property(nonatomic,strong)dispatch_queue_t money_queue;

@end

@implementation dispatch_queue_serial_test

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.queue = dispatch_queue_create("com.bien.serial_queue", DISPATCH_QUEUE_SERIAL);
    }
    
    return self;
}




- (void)test
{
    for (int i = 0; i < 10; i++) {
        NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(_test:) object:@(i) ];
        [thread setName:[NSString stringWithFormat:@"子-%d",I]];
        [thread start];
    }
}

- (void)_test:(NSNumber *)index
{
    dispatch_sync(self.queue, ^{
        sleep(1);
        NSLog(@"%@",[NSThread currentThread]);
    });

}

@end


  • NSLock

NSLock是对pthread_mutex_t 的封装

@interface NSLock_Test ()

@property(nonatomic,strong)NSLock *tlock;
@end

@implementation NSLock_Test

- (instancetype)init
{
    self = [super init];
    if (self) {

        self.lock = [[NSLock alloc] init];
    }
    
    return self;
}

- (void)sale_tickets
{
    [self.lock lock];
    
  //code here

    
    [self.lock unlock];
    
}

@end

  • NSRecursiveLock

NSRecursiveLock是对pthread_mutex_t递归锁的封装

@interface NSRecursiveLock_Test ()

@property(nonatomic,strong)NSRecursiveLock recursiveLock;



@end

@implementation NSRecursiveLock_Test

- (instancetype)init
{
    self = [super init];
    if (self) {
        self. recursiveLock = [[NSRecursiveLock alloc] init];
    }
    
    return self;
}

- (void)test
{
    [self.tickets_lock lock];
    
    static int count = 0;
    if (count < 10) {
        NSLog(@"%d,%s",count, __func__);
        count++;
        [self test];
    }
    
    
    [self.tickets_lock unlock];
}

@end


  • NSCondition

NSCondition是对mutex和cond的封装

@interface NSCondition_Test ()

@property(nonatomic,strong)NSCondition *cond;
@property(nonatomic,strong)NSMutableArray *data;

@end

@implementation NSCondition_Test

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.cond = [[NSCondition alloc] init];
        self.data = [[NSMutableArray alloc] init];
    }
    
    return self;
}

- (void)test
{
    [[[NSThread alloc] initWithBlock:^{
        [self.cond lock];
        NSLog(@"--remove-begin--");
        if (self.data.count == 0) {
//            [self.cond wait];
            [self.cond waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:3.0] ];
        }
        
        [self.data removeLastObject];
        
        NSLog(@"remove completion");
        [self.cond unlock];
        }] start] ;
    
    
    [[[NSThread alloc] initWithBlock:^{
        [self.cond lock];
        [self.data addObject:@"abc"];
        NSLog(@"add completion");
        [self.cond unlock];
        
        sleep(5);
        NSLog(@"signal will be sent out");
        [self.cond signal];
        NSLog(@"signal has been sent out");

        
//        [self.cond broadcast];
        }] start] ;

}



@end


  • NSConditionLock

NSConditionLock是对NSCondition的进一步封装,可以设置条件值

@interface NSConditionLock_Test ()
@property(nonatomic,strong)NSConditionLock *conditionLock;

@end

@implementation NSConditionLock_Test

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.conditionLock = [[NSConditionLock alloc] initWithCondition:1024];
    }
    
    return self;
}

- (void)test
{
    [[[NSThread alloc] initWithBlock:^{
        [[NSThread currentThread] setName:@"1024"];
        [self.conditionLock lockWhenCondition:1024];
        NSLog(@"%@",[NSThread currentThread]);
        [self.conditionLock lockBeforeDate:[NSDate dateWithTimeIntervalSinceNow:2]];
        [self.conditionLock unlockWithCondition:2048];
    }] start];
    
    [[[NSThread alloc] initWithBlock:^{
        [[NSThread currentThread] setName:@"2048"];

        [self.conditionLock lockWhenCondition:2048];
        NSLog(@"%@",[NSThread currentThread]);
        [self.conditionLock lockBeforeDate:[NSDate dateWithTimeIntervalSinceNow:1]];


        [self.conditionLock unlockWithCondition:5012];
    }] start];
    
    [[[NSThread alloc] initWithBlock:^{
        [[NSThread currentThread] setName:@"5012"];

        [self.conditionLock lockWhenCondition:5012];
        NSLog(@"%@",[NSThread currentThread]);
        [self.conditionLock lockBeforeDate:[NSDate dateWithTimeIntervalSinceNow:3]];

        [self.conditionLock unlock];
        NSLog(@"unLocked finished");
    }] start];

}

@end

  • @synchronized

@synchronized是对mutex递归锁的封装
源码objc4中 objc-sync.mm文件
@ synchronized(obj)内部会生成obj对应的的递归锁,然后进行加锁、解锁操作

@synchronized(self.class)
{
        //code here
}
  • atomic

atomic用于保证setter\getter 方法的原子性操作,相当于在setter/getter方法内部加了线程同步的锁
参考objc4中objc_accessors.mm
不能保证属性的过程是线程安全的

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 多线程的锁大致可分为两大类:互斥锁、自旋锁;也可以分为三类:互斥锁、自旋锁、读写锁。 一、互斥锁:互斥+同步(强调...
    spyn_n阅读 3,355评论 0 2
  • Q:为什么出现多线程? A:为了实现同时干多件事的需求(并发),同时进行着下载和页面UI刷新。对于处理器,为每个线...
    幸福相依阅读 5,531评论 0 2
  • 多线程需要一种互斥的机制来访问共享资源。 一、 互斥锁 互斥锁的意思是某一时刻只允许一个线程访问某一资源。为了保证...
    doudo阅读 4,084评论 0 5
  • 前言 iOS开发中由于各种第三方库的高度封装,对锁的使用很少,刚好之前面试中被问到的关于并发编程锁的问题,都是一知...
    KingWorld阅读 4,819评论 0 0
  • 目录:1.为什么要线程安全2.多线程安全隐患分析3.多线程安全隐患的解决方案4.锁的分类-13种锁4.1.1OSS...
    二斤寂寞阅读 4,868评论 0 3