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];
}