os_unfair_lock 与pthread_mutex(普通锁,递归锁,条件锁)与(NSLock,NSRecursiveLock,NSCondition,NSConditionLock)

os_unfair_lock
os_unfair_lock用于取代不安全的OSSpinLock,从iOS10开始才支持.
从底层调用看,等待os_unfair_lock锁的线程会处于休眠状态,并非忙等
使用时需要导入头文件#import

 // 初始化
 os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
 //尝试加锁
 os_unfair_lock_trylock(&lock);
 // 加锁
 os_unfair_lock_lock(&lock);
 // 解锁
 os_unfair_lock_unlock(&lock);

封装多线程,然后用相应的锁进行加锁解锁
MHFBaseDemo.h

#import 
@interface MHFBaseDemo : NSObject

- (void)moneyTest;
- (void)ticketTest;

#pragma mark - 暴露给子类使用
- (void)__saveMoney;
- (void)__drawMoney;
- (void)__saleTicket;
@end

MHFBaseDemo.m

#import "MHFBaseDemo.h"

@interface MHFBaseDemo ()
@property (nonatomic, assign) int money;
@property (nonatomic, assign) int ticketCount;
@end
@implementation MHFBaseDemo
- (void)__saveMoney
{
    int oldMoney = self.money;
    sleep(.2);
    oldMoney += 20;
    self.money = oldMoney;
    NSLog(@"剩余%d钱,---%@----",oldMoney,[NSThread currentThread]);
}

- (void)__drawMoney
{
    int oldMoney = self.money;
    sleep(.2);
    oldMoney -= 20;
    self.money = oldMoney;
    NSLog(@"剩余%d钱,---%@----",oldMoney,[NSThread currentThread]);
}

- (void)__saleTicket
{
    int oldTicket = self.ticketCount;
    sleep(.2);// 为了使多线程安全问题更加突出明显
    oldTicket--;
    self.ticketCount = oldTicket;
    NSLog(@"还剩%d张票,-%@",oldTicket,[NSThread currentThread]);
}


- (void)moneyTest
{
    self.money = 100;
    dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        [self __saveMoney];
    });
    dispatch_async(queue, ^{
        [self __drawMoney];
    });
    dispatch_async(queue, ^{
        [self __saveMoney];
    });
    dispatch_async(queue, ^{
        [self __drawMoney];
    });
    
}


// 卖票演示
- (void)ticketTest
{
    self.ticketCount = 15;
    dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        for (int i = 0; i < 5; i++) {
            [self __saleTicket];
        }
    });
    
    dispatch_async(queue, ^{
        for (int i = 0; i < 5; i++) {
            [self __saleTicket];
        }
    });
    
    dispatch_async(queue, ^{
        for (int i = 0; i < 5; i++) {
            [self __saleTicket];
        }
    });
}
@end

OSUnfairLockDemo.h

#import "MHFBaseDemo.h"
#import 
@interface OSUnfairLockDemo : MHFBaseDemo
@end

OSUnfairLockDemo.m

#import "OSUnfairLockDemo.h"
#import 
@interface OSUnfairLockDemo ()
/*注意点:
 typedef struct os_unfair_lock_s {
 uint32_t _os_unfair_lock_opaque;
 } os_unfair_lock, *os_unfair_lock_t;
 因为os_unfair_lock定义的是一个结构体,所以用的是assign不能用strong
 */
@property (nonatomic, assign) os_unfair_lock moneyLock;
@property (nonatomic, assign) os_unfair_lock ticketLock;
@end

@implementation OSUnfairLockDemo

- (instancetype)init
{
    if (self = [super init]) {
        self.moneyLock = OS_UNFAIR_LOCK_INIT;
        self.ticketLock = OS_UNFAIR_LOCK_INIT;
    }
    return self;
}

- (void)__saleTicket
{
    os_unfair_lock_lock(&_ticketLock);
    [super __saleTicket];
    os_unfair_lock_unlock(&_ticketLock);
}


- (void)__saveMoney
{
     os_unfair_lock_lock(&_moneyLock);
    [super __saveMoney];
     os_unfair_lock_unlock(&_moneyLock);
}

- (void)__drawMoney
{
     os_unfair_lock_lock(&_moneyLock);
    [super __drawMoney];
     os_unfair_lock_unlock(&_moneyLock);
}

@end

pthread_mutex
pthread_mutex 普通锁
mutex叫做互斥锁,等待锁的线程会处于休眠状态
导入头文件#import

 // 初始化锁的属性
 pthread_mutexattr_t attr;
 pthread_mutexattr_init(&attr);
 pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_NORMAL);
 
 //锁的类型
 #define PTHREAD_MUTEX_NORMAL 0
 #define PTHREAD_MUTEX_ERRORCHECK 0 // 检测错误的锁
 #define PTHREAD_MUTEX_RECURSIVE 0   // 递归锁
 #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL
 
 // 初始化锁
 pthread_mutex_t mutex;
 pthread_mutex_init(&mutex,&attr);
 // 尝试加锁
 pthread_mutex_trylock(&mutex);
 // 加锁
 pthread_mutex_lock(&mutex);
 // 解锁
 pthread_mutex_unlock(&mutex);
 // 销毁相关资源
 pthread_mutexattr_destroy(&attr);
 pthread_mutex_destroy(&mutex);

MutexLockDemo.h

#import "MHFBaseDemo.h"
@interface MutexLockDemo : MHFBaseDemo
@end

MutexLockDemo.m

#import "MutexLockDemo.h"
#import 
@interface MutexLockDemo ()
/*

 */
@property (nonatomic, assign) pthread_mutex_t moneyMutex;
@property (nonatomic, assign) pthread_mutex_t ticketMutex;
@end
@implementation MutexLockDemo

- (instancetype)init
{
    if (self = [super init]) {
        /*
         self.moneyLock = PTHREAD_MUTEX_INITIALIZER; 直接定义出错
         #define PTHREAD_MUTEX_INITIALIZER {_PTHREAD_MUTEX_SIG_init, {0}}
         PTHREAD_MUTEX_INITIALIZER是一个宏定义,{_PTHREAD_MUTEX_SIG_init, {0}}这个结构体就是这个 PTHREAD_MUTEX_INITIALIZER
         相等于
          self.moneyLock = {_PTHREAD_MUTEX_SIG_init, {0}}
         如果在定义变量的同时给赋值结构体运行这样做即pthread_mutex_t moneyLock = PTHREAD_MUTEX_INITIALIZER;是可以的
        
        struct Date {
            int year;
            int month;
        };
        struct Date date = {2018,11};// 定义结构体变量的同时给结构体变量赋值是可以的,
        
         
        struct Date date1; // 定义变量后,g再给结构体赋值是不可以的,报错
        date1 = {2019,11};
         
         静态初始化
         pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
         
       */
        
       
        [self __initMutex:&_moneyMutex];
        [self __initMutex:&_ticketMutex];
        
    }
    return self;
}


- (void) __initMutex:(pthread_mutex_t *)mutex
{
    // 动态初始化
    
    // 初始化这把锁带有的属性
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    // 设置这把锁属性的类型
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
    
    // 初始化这把锁
    pthread_mutex_init(mutex, &attr);
    
    // 销毁属性
    pthread_mutexattr_destroy(&attr);
}

- (void)__saleTicket
{
    pthread_mutex_lock(&_ticketMutex);
   
    [super __saleTicket];
     pthread_mutex_unlock(&_ticketMutex);
  
}


- (void)__saveMoney
{
  
     pthread_mutex_lock(&_moneyMutex);
    [super __saveMoney];
     pthread_mutex_unlock(&_moneyMutex);
   
}

- (void)__drawMoney
{
    pthread_mutex_lock(&_moneyMutex);
    [super __drawMoney];
     pthread_mutex_unlock(&_moneyMutex);

}
@end

外部调用这两把锁

#import "MHFBaseThreadVC.h"
#import "OSSpinLockDemo.h"
#import "MutexLockDemo.h"
@interface MHFBaseThreadVC ()

@end

@implementation MHFBaseThreadVC


- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
   
    [self mutexLock];
    
    
}


- (void)mutexLock
{
    MutexLockDemo *mutexLock = [[MutexLockDemo alloc]init];
    [mutexLock ticketTest];
    [mutexLock moneyTest];
}

- (void)osspinLock
{
    OSSpinLockDemo *spinLock = [[OSSpinLockDemo alloc]init];
        [spinLock ticketTest];
        [spinLock moneyTest];
}

@end

pthread_mutex 递归锁
MutexLockDemo2.h

#import "MHFBaseDemo.h"
@interface MutexLockDemo2 : MHFBaseDemo
@end

MutexLockDemo2.m

#import "MutexLockDemo2.h"

#import 
@interface MutexLockDemo2 ()

@property (nonatomic, assign) pthread_mutex_t mutex;

@end
@implementation MutexLockDemo2

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


- (void) __initMutex:(pthread_mutex_t *)mutex
{
    // 动态初始化
    
    // 初始化这把锁带有的属性
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    // 设置这把锁属性的类型
    //PTHREAD_MUTEX_RECURSIVE递归锁,允许同一个线程对同一把锁进行重复加锁
    // 递归锁也可以解决多线程同步的问题
    /*
     线程1: otherTest(+-)
                otherTest(+-)
                    otherTest(+-)
     线程2: otherTest(等待)
     如果线程1已经对这把锁进行加锁了,线程2也调用otherTest发现这把锁被别的线程加锁了,所以线程2就不能加锁,线程2就会在这里等待
     */
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    
    // 初始化这把锁
    pthread_mutex_init(mutex, &attr);
    
    // 销毁属性
    pthread_mutexattr_destroy(&attr);
}

- (void)otherTest
{
    pthread_mutex_lock(&_mutex);
    static int count = 0;
    count++;
    NSLog(@"%s",__func__);
    if (count < 10) {
        [self otherTest];
    }
//    [self otherTest];// 这种线性叫死锁
    pthread_mutex_unlock(&_mutex);
}

- (void)otherTest2
{
    pthread_mutex_lock(&_mutex);
     NSLog(@"%s",__func__);
    pthread_mutex_unlock(&_mutex);
    
}
- (void)dealloc
{
    pthread_mutex_destroy(&_mutex);

}
@end

pthread_mutex 条件锁
外部调用

 MutexLockDemo3 *mutexLock = [[MutexLockDemo3 alloc]init];
    [mutexLock otherTest];

MutexLockDemo3.h

#import "MHFBaseDemo.h"
@interface MutexLockDemo3 : MHFBaseDemo
@end

MutexLockDemo3.m

#import "MutexLockDemo3.h"
#import 
@interface MutexLockDemo3 ()
@property (assign, nonatomic) pthread_mutex_t mutexLock;
@property (assign, nonatomic) pthread_cond_t conditionLock;
@property (nonatomic, strong) NSMutableArray *dataArray;
@end
@implementation MutexLockDemo3

- (instancetype)init
{
    self = [super init];
    if (self) {
        pthread_mutexattr_t mutexAttr;
        pthread_mutexattr_init(&mutexAttr);
        pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_NORMAL);
        
        pthread_mutex_init(&_mutexLock, &mutexAttr);
        pthread_mutexattr_destroy(&mutexAttr);
        self.dataArray = [NSMutableArray array];
        
        // 初始化条件锁
        pthread_cond_init(&_conditionLock, NULL);
   
    }
    return self;
}

- (void)__add
{
    pthread_mutex_lock(&_mutexLock);
    NSLog(@"begin add");
    [self.dataArray addObject:@"Test"];
    pthread_cond_signal(&_conditionLock);
     NSLog(@"middle add");
    pthread_mutex_unlock(&_mutexLock);
     NSLog(@"end add");
}

- (void)__remove
{
    pthread_mutex_lock(&_mutexLock);
    sleep(.2);
    NSLog(@"begin remove");
    
    if (self.dataArray.count == 0) {
        NSLog(@"middle 1 remove");
        pthread_cond_wait(&_conditionLock, &_mutexLock);
        NSLog(@"middle 2 remove");
    }
     [self.dataArray removeLastObject];
    NSLog(@"end remove");
    pthread_mutex_unlock(&_mutexLock);
}
- (void)otherTest
{
    [[[NSThread alloc]initWithTarget:self selector:@selector(__remove) object:nil]start];
    [[[NSThread alloc]initWithTarget:self selector:@selector(__add) object:nil]start];
}
- (void)dealloc
{
    pthread_mutex_destroy(&_mutexLock);
    pthread_cond_destroy(&_conditionLock);
}
@end
/*
打印结果:
2018-11-16 08:00:44.059 OCTestFirst[3827:45553] begin remove
2018-11-16 08:00:48.453 OCTestFirst[3827:45553] middle 1 remove
2018-11-16 08:00:48.454 OCTestFirst[3827:45554] begin add
2018-11-16 08:00:48.454 OCTestFirst[3827:45554] middle add
2018-11-16 08:00:48.455 OCTestFirst[3827:45554] end add
2018-11-16 08:00:48.455 OCTestFirst[3827:45553] middle 2 remove
2018-11-16 08:00:48.458 OCTestFirst[3827:45553] end remove
条件锁:__remove这个方法是,当dataArray.count == 0的时候,就给一个条件_conditionaLock,同时解锁_mutexLock,,然后这个线程进入睡眠,等待这个条件发送信号,直到__add方法对_mutexLock加锁后dataArray中添加了对象,然后发送信号给_conditionLock,再对_mutexLock解锁后,__remove方法唤响上次等待这个条件的线程,
再对其_mutexLock进行加锁,执行了[self.dataArray removeLastObject];后再 pthread_mutex_unlock(&_mutexLock);然后完成整个过程.
其中__remove方法中的 pthread_cond_wait(&_conditionLock, &_mutexLock);做了三件事情第一件事情,给了一个等待的条件,第二件事情对_mutexLock进行解锁,第三件事情使改线程进入休眠.
*/

NSLock,NSRecursiveLock,NSCondition
NSLock与NSRecursiveLock是对pthread_mutex锁的属性为normal与recursive的封装;
NSCondtion是对pthread_mutex和condition的封装.NSConditionLock是对NSCondtion的进一步封装,下面写下NSCondition与NSCondtionLock的应用:

NSCondtion应用
NSConditionDemo.h

#import "MHFBaseDemo.h"
@interface NSConditionDemo : MHFBaseDemo
@end

NSConditionDemo.m

#import "NSConditionDemo.h"

@interface NSConditionDemo ()
@property (nonatomic, strong) NSCondition *condition;
@property (nonatomic, strong) NSMutableArray *dataArray;
@end

@implementation NSConditionDemo
- (instancetype)init
{
    if (self = [super init]) {
        _condition = [[NSCondition alloc]init];
        _dataArray = [NSMutableArray array];
    }
    return self;
}


- (void)__add
{
    [self.condition lock];
    NSLog(@"begin add");
    [self.dataArray addObject:@"Test"];
    [self.condition signal];
    NSLog(@"middle add");
    [self.condition unlock];
    NSLog(@"end add");
}

- (void)__remove
{
    
    [self.condition lock];
    sleep(.2);
    NSLog(@"begin remove");
    
    if (self.dataArray.count == 0) {
        NSLog(@"middle 1 remove");
        [self.condition wait];
        NSLog(@"middle 2 remove");
    }
    [self.dataArray removeLastObject];
    NSLog(@"end remove");
    [self.condition unlock];
}


- (void)otherTest
{
    [[[NSThread alloc]initWithTarget:self selector:@selector(__remove) object:nil]start];
    [[[NSThread alloc]initWithTarget:self selector:@selector(__add) object:nil]start];
    
}
@end

NSCondtionLock的应用
多线程顺序执行任务
NSConditonLockDemo.h

#import "MHFBaseDemo.h"
@interface NSConditonLockDemo : MHFBaseDemo
@end

NSConditonLockDemo.m

#import "NSConditonLockDemo.h"

@interface NSConditonLockDemo ()

@property (nonatomic, strong) NSConditionLock *conditionLock;
@end
@implementation NSConditonLockDemo

- (instancetype)init
{
    if (self = [super init]) {
        _conditionLock = [[NSConditionLock alloc]initWithCondition:1];

    }
    return self;
}

- (void)threadFirst
{
    [self.conditionLock lockWhenCondition:1];
    NSLog(@"__one");
    [self.conditionLock unlockWithCondition:2];
}
- (void)threadSecond
{
    [self.conditionLock lockWhenCondition:2];
    NSLog(@"__two");
    [self.conditionLock unlockWithCondition:3];
    
}
- (void)threadThree
{
    [self.conditionLock lockWhenCondition:3];
    NSLog(@"__three");
    [self.conditionLock unlock];
}

- (void)otherTest
{
    [[[NSThread alloc]initWithTarget:self selector:@selector(threadFirst) object:nil]start];
    [[[NSThread alloc]initWithTarget:self selector:@selector(threadSecond) object:nil]start];
    [[[NSThread alloc]initWithTarget:self selector:@selector(threadThree) object:nil]start];
}

你可能感兴趣的:(iOS-开发知识点)