zoukankan      html  css  js  c++  java
  • iOS 线程同步 自旋锁 互斥锁

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

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

     

    #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];
            }
        });
    }
  • 相关阅读:
    Mysql登录错误:ERROR 1045 (28000): Plugin caching_sha2_password could not be loaded
    Docker配置LNMP环境
    Docker安装mysqli扩展和gd扩展
    Docker常用命令
    Ubuntu常用命令
    单例模式的优缺点和使用场景
    ABP 多租户数据共享
    ABP Core 后台Angular+Ng-Zorro 图片上传
    ERROR Error: If ngModel is used within a form tag, either the name attribute must be set or the form control must be defined as 'standalone' in ngModelOptions.
    AbpCore 执行迁移文件生成数据库报错 Could not find root folder of the web project!
  • 原文地址:https://www.cnblogs.com/ZhangShengjie/p/12275038.html
Copyright © 2011-2022 走看看