iOS 线程同步 自旋锁 OSSpinLock

Posted ZhangShengjie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS 线程同步 自旋锁 OSSpinLock相关的知识,希望对你有一定的参考价值。

 线程同步的本质是每一条线程的同步都是按顺序的

=====================================================================================================================

 

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

 

以上是关于iOS 线程同步 自旋锁 OSSpinLock的主要内容,如果未能解决你的问题,请参考以下文章

多线程安全问题及各种锁

iOS之深入解析“锁”的底层原理

IOS面试题(多线程) --- 锁

iOS - 多线程的锁

使用编译器内在函数实现自旋锁以同步 OpenMP 线程

浅谈自旋锁和 JVM 对锁的优化