多線程-鎖

  • OSSpinLock
    1>自旋鎖,等待鎖的線程會(huì)處于忙等(busy-wait)狀態(tài),始終占著CPU資源;
    2>實(shí)現(xiàn)原理:相當(dāng)于執(zhí)行一個(gè)while循環(huán);
    3>目前已經(jīng)不再安全,可能出現(xiàn)優(yōu)先級(jí)反轉(zhuǎn)問題,如果等待鎖的線程優(yōu)先級(jí)比較高,它會(huì)一直占著CPU資源,優(yōu)先級(jí)低的線程就無法解鎖;

多線程實(shí)現(xiàn):利用時(shí)間片調(diào)度算法
線程優(yōu)先級(jí):優(yōu)先級(jí)高的線程分配的時(shí)間比較多,優(yōu)先級(jí)低的線程分配的時(shí)間比較少

#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鎖的線程,處于休眠狀態(tài),而非忙等
#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>互斥鎖,等待鎖的線程會(huì)處于 休眠狀態(tài)
#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(@"數(shù)組中沒有數(shù)據(jù)");
           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 - 信號(hào)量
    2> 信號(hào)量的的初始值,可以控制線程并發(fā)訪問的最大量
    3> 信號(hào)量的初始值為1,代表同時(shí)只允許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);
}

  • 串行隊(duì)列
@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是對(duì)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是對(duì)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是對(duì)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是對(duì)NSCondition的進(jìn)一步封裝,可以設(shè)置條件值

@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是對(duì)mutex遞歸鎖的封裝
源碼objc4中 objc-sync.mm文件
@ synchronized(obj)內(nèi)部會(huì)生成obj對(duì)應(yīng)的的遞歸鎖,然后進(jìn)行加鎖、解鎖操作

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

atomic用于保證setter\getter 方法的原子性操作,相當(dāng)于在setter/getter方法內(nèi)部加了線程同步的鎖
參考o(jì)bjc4中objc_accessors.mm
不能保證屬性的過程是線程安全的

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 多線程的鎖大致可分為兩大類:互斥鎖、自旋鎖;也可以分為三類:互斥鎖、自旋鎖、讀寫鎖。 一、互斥鎖:互斥+同步(強(qiáng)調(diào)...
    spyn_n閱讀 642評(píng)論 0 2
  • Q:為什么出現(xiàn)多線程? A:為了實(shí)現(xiàn)同時(shí)干多件事的需求(并發(fā)),同時(shí)進(jìn)行著下載和頁(yè)面UI刷新。對(duì)于處理器,為每個(gè)線...
    幸福相依閱讀 1,732評(píng)論 0 2
  • 多線程需要一種互斥的機(jī)制來訪問共享資源。 一、 互斥鎖 互斥鎖的意思是某一時(shí)刻只允許一個(gè)線程訪問某一資源。為了保證...
    doudo閱讀 824評(píng)論 0 5
  • 前言 iOS開發(fā)中由于各種第三方庫(kù)的高度封裝,對(duì)鎖的使用很少,剛好之前面試中被問到的關(guān)于并發(fā)編程鎖的問題,都是一知...
    KingWorld閱讀 1,270評(píng)論 0 0
  • 目錄:1.為什么要線程安全2.多線程安全隱患分析3.多線程安全隱患的解決方案4.鎖的分類-13種鎖4.1.1OSS...
    二斤寂寞閱讀 1,248評(píng)論 0 3

友情鏈接更多精彩內(nèi)容