OC原理之多线程中的锁(一)

OSSpinLock

OSSpinLock叫做"自旋锁",等待锁的线程会处于忙等状态,一直占用着cpu资源。由于可能会出现优先级反转的问题,是个不安全锁。在iOS10苹果已经不推荐使用了

优先级反转问题

如果等待锁的线程优先级较高,它会一直占用着CPU资源,优先级低的线程就无法释放 使用的时候需要导入#import <libkern/OSAtomic.h>

使用代码

OSSpinLock lock = OS_SPINLOCK_INIT;
bool result = OSSpinLockTry(lock);// 尝试加锁(如果需要等待就不加锁,直接返回false,如果不需要等待就加锁,返回true)
OSSpinLockLock(lock); // 加锁
OSSpinLockUnlock(lock);// 不加锁

os_unfair_lock

os_unfair_lock用于取代不安全的OSSpinLock,iOS10以后才支持

相比较于OSSpinLock的区别,等待os_unfair_lock锁的线程会处于休眠状态,并非忙等

使用时,如要导入头文件#import <os/lock.h>

使用代码

os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
bool result = os_unfair_lock_trylock(&lock); // 尝试加锁 返回值=是否加锁成功
os_unfair_lock_lock(&lock); // 加锁
os_unfair_lock_unlock(&lock); // 解锁

pthread_mutex

mutex叫做"互斥锁",等待锁的线程会处于休眠状态

需要导入头文件#import <pthread.h>

使用代码

// 初始化锁的属性
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
    
// 初始化锁
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, &attr);
    
// 尝试加锁
bool result = pthread_mutex_trylock(&mutex);
    
// 加锁
pthread_mutex_lock(&mutex);
    
// 解锁
pthread_mutex_unlock(&mutex);
    
// 销毁相关资源
pthread_mutexattr_destroy(&attr);
pthread_mutex_destroy(&mutex);

pthread_mutex - 递归锁

递归锁的话,创建方式与互斥锁的方式相同,只是在创建pthread_mutexattr_t的之后,设置类型为PTHREAD_MUTEX_RECURSIVE

pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);

pthread_mutex – 条件

使用代码:

// 初始化锁
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
    
// 初始化条件
pthread_cond_t condition;
pthread_cond_init(&condition, NULL);
    
// 等待条件(进入休眠,放开mutex锁,被唤醒后,会再次对mutex加锁)
pthread_cond_wait(&condition, &mutex);
// 激活一个等待该条件的线程
pthread_cond_signal(&condition);
// 激活所有等待该条件的线程
pthread_cond_broadcast(&condition);
    
// 销毁
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&condition);

NSLock

NSLock是对mutex普通锁的封装

NSRecursiveLock

NSrecursiveLock是对mutex递归锁的封装

NSCondition

NSCondition是对mutex和cond的封装

dispatch_semaphore

semaphore叫做"信号量"

信号量的初始值,可以用来控制线程并发访问的最大数量

信号量的初始值为1,代表同时只允许一条线程访问资源,保证线程同步

使用代码:

// 信号量的初始值
int value = 1;
// 初始化信号量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(value);
// 如果信号量的值<=0,当前线程就会进入休眠等待(知道信号量的值>0)
// 如果信号量的值>0,就减1,然后往下执行后面的代码
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// 让信号量的值加1
dispatch_semaphore_signal(semaphore);

dispatch_queue

直接使用GCD的串行队列,也是可以显示线程同步的

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
        
});

@synchronized

@synchronized是对mutex递归锁的封装

源码查看:objc4中的objc-sync.mm文件

@synchronized(obj)内部会生成obj对应的递归锁,然后进行加锁、解锁操作

使用代码:

@synchronized (object) {
        
}

 

posted @ 2021-02-24 21:18  木子沉雨  阅读(387)  评论(0编辑  收藏  举报