线程同步的本质是每一条线程的同步都是按顺序的
=====================================================================================================================
#import "ViewController.h" #import <libkern/OSAtomic.h> @interface ViewController () @property (nonatomic,assign) int ticket; //@property (nonatomic,assign) OSSpinLock lock; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // self.lock = OS_SPINLOCK_INIT; self.ticket=50; [self ticketsTest]; // Do any additional setup after loading the view. } -(void)saleTicket{ //静态创建、则不需要新建属性 static OSSpinLock lock = OS_SPINLOCK_INIT; //若后面是个函数、则需 /* static OSSpinLock lock = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ lock = OS_SPINLOCK_INIT; }); */ //其他线程执行到这里时,发现锁被加锁了 就会再这排队等待、直到这个锁被打开 //加锁 OSSpinLockLock(&lock); int ticket = self.ticket; sleep(.2); ticket--; self.ticket=ticket; NSLog(@"%d",self.ticket); //解锁 OSSpinLockUnlock(&lock); } -(void)ticketsTest{ dispatch_queue_t queue = dispatch_get_global_queue(0, 0); dispatch_async(queue, ^{ for (int i =0; i<5; i++) { [self saleTicket]; } }); dispatch_async(queue, ^{ for (int i =0; i<5; i++) { [self saleTicket]; } }); }
#import "ViewController.h" #import <pthread.h> @interface ViewController () @property (nonatomic,assign) int ticket; @property (nonatomic,assign) pthread_mutex_t mutex; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //初始化锁的属性 pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT); //PTHREAD_MUTEX_RECURSIVE 递归锁 同一个线程对同一个锁能多次加锁 //初始化锁 pthread_mutex_init(&_mutex, &attr); //销毁属性 pthread_mutexattr_destroy(&attr); self.ticket=50; [self ticketsTest]; // Do any additional setup after loading the view. } -(void)saleTicket{ pthread_mutex_lock(&_mutex); int ticket = self.ticket; sleep(.2); ticket--; self.ticket=ticket; NSLog(@"%d",self.ticket); pthread_mutex_unlock(&_mutex); } -(void)ticketsTest{ dispatch_queue_t queue = dispatch_get_global_queue(0, 0); dispatch_async(queue, ^{ for (int i =0; i<5; i++) { [self saleTicket]; } }); dispatch_async(queue, ^{ for (int i =0; i<5; i++) { [self saleTicket]; } }); } -(void)dealloc{ //销毁锁 pthread_mutex_destroy(&_mutex); } @end
pthread_mutex – 条件锁
使用场景 两个线程同时执行,其中一个线程要在另外一个线程执行完成之后才能执行
#import "ViewController.h" #import <pthread.h> @interface ViewController () @property (nonatomic,assign) pthread_mutex_t mutex; @property (nonatomic, strong) NSMutableArray *data; @property (nonatomic,assign) pthread_cond_t cond; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //初始化锁的属性 pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT); //PTHREAD_MUTEX_RECURSIVE 递归锁 同一个线程对同一个锁能多次加锁 //初始化锁 pthread_mutex_init(&_mutex, &attr); //销毁属性 pthread_mutexattr_destroy(&attr); //创建条件 pthread_cond_init(&_cond, NULL); self.data = [NSMutableArray array]; [self test]; // Do any additional setup after loading the view. } //同时执行 删除 添加操作 -(void)test{ [[[NSThread alloc]initWithTarget:self selector:@selector(add) object:nil] start]; [[[NSThread alloc]initWithTarget:self selector:@selector(remove) object:nil] start]; } -(void)add{ sleep(1); pthread_mutex_lock(&_mutex); [self.data addObject:@"A"]; NSLog(@"添加数据"); //发送信号通知条件能继续往下执行 // pthread_cond_signal(&_cond); //广播信号 对应的条件能往下继续执行了 pthread_cond_broadcast(&_cond); pthread_mutex_unlock(&_mutex); } -(void)remove{ NSLog(@"开始删除数据"); pthread_mutex_lock(&_mutex); if (self.data.count==0) { //这时候会等待条件、并且打开当前锁、 //收到条件信号之后会重新加锁并执行后面的代码 pthread_cond_wait(&_cond, &_mutex); } [self.data removeLastObject]; pthread_mutex_unlock(&_mutex); NSLog(@"删除数据"); } -(void)dealloc{ //销毁锁 pthread_mutex_destroy(&_mutex); //销毁条件 pthread_cond_destroy(&_cond); } @end
串行队列也能解决线程同步问题 保证统一时刻只执行一个线程
#import "ViewController.h" @interface ViewController () @property (nonatomic,assign) int ticket; @property (nonatomic, strong) dispatch_queue_t queue; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.queue=dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL); self.ticket=50; [self ticketsTest]; // Do any additional setup after loading the view. } -(void)saleTicket{ dispatch_sync(self.queue, ^{ int ticket = self.ticket; sleep(.2); ticket--; self.ticket=ticket; NSLog(@"%d-=%@",self.ticket,[NSThread currentThread]); }); } -(void)ticketsTest{ dispatch_queue_t queue = dispatch_get_global_queue(0, 0); dispatch_async(queue, ^{ for (int i =0; i<5; i++) { [self saleTicket]; } }); dispatch_async(queue, ^{ for (int i =0; i<5; i++) { [self saleTicket]; } }); }