iOS开发中的递归锁之pthread_mutex_t

我们知道递归就是自己调用自己即一个方法内部又调用了这个方法本身。那么什么是递归锁呢?

递归锁

递归锁是应用在递归调用中的,它可以防止在递归调用中使用普通锁造成的死锁。
在介绍递归锁之前先演示一下普通锁在递归调用中的问题,看代码:

  - (void)test{
pthread_mutex_lock(&_mutex);
NSLog(@"%s", __func__);
static int num = 0;
if (num < 10) {
    num ++;
    [self test];
}
pthread_mutex_unlock(&_mutex);
}

我们这篇文章中介绍锁是pthread_mutex_t,它的初始化方法如下:

  - (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)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor greenColor];
[self __initMutex:&_mutex];
}

其中的PTHREAD_MUTEX_NORMAL代表它是一把普通的锁。看打印结果:

   6.pthread_mutex_t[1253:28817] -[ViewController test]
 6.pthread_mutex_t[1253:28861] XPC connection interrupted

test方法只被调用了一次,和我们预期的并不一样,这是为什么呢?

死锁

在递归调用中使用普通的锁,出现了死锁。为什么会出现死锁呢?我们分析一下。

第一次调用test方法的时候,我们进行了加锁,在解锁之前我们又调用了test方法。第二次调用test方法的时候本来要对同一把锁进行加锁,可发现这把锁已经被加锁了,于是线程进入了休眠(pthread_mutex_t是一把互斥锁)等待解锁。线程休眠无法继续往下执行第一次加锁无法解锁于是就造成了死锁。

使用递归锁

在初始化锁的时候我们使用递归锁,

  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);

使用递归锁之后,打印结果就完全没问题了。
为什么使用递归锁就能防止死锁呢?这是因为递归锁能够对同一把锁重复加锁。

问:如果多个线程同时调用test方法,那递归锁岂不是不能保证线程的安全?
答:递归锁只允许同一个线程对同一把锁进行重复加锁。
注意:在使用pthread_mutex_t结束之后要进行销毁。

  - (void)dealloc{
pthread_mutex_destroy(&_mutex);
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 锁是一种同步机制,用于多线程环境中对资源访问的限制iOS中常见锁的性能对比图(摘自:ibireme): iOS锁的...
    LiLS阅读 1,553评论 0 6
  • 转自(https://bestswifter.com/ios-lock/#) 深入理解 iOS 开发中的锁 摘要 ...
    犯色戒的和尚阅读 337评论 0 1
  • Q:为什么出现多线程? A:为了实现同时干多件事的需求(并发),同时进行着下载和页面UI刷新。对于处理器,为每个线...
    幸福相依阅读 1,613评论 0 2
  • 前言 在多线程开发中,常会遇到多个线程访问修改数据。为了防止数据不一致或数据污染,通常采用加锁机制来保证线程安全。...
    赵梦楠阅读 1,005评论 0 5
  • 目录:1.为什么要线程安全2.多线程安全隐患分析3.多线程安全隐患的解决方案4.锁的分类-13种锁4.1.1OSS...
    二斤寂寞阅读 1,197评论 0 3