在Swift中移动互斥体安全吗



我对互斥进行了一些研究,发现了以下Swift代码:

class Lock {
private var mutex: pthread_mutex_t = {
var mutex = pthread_mutex_t()
pthread_mutex_init(&mutex, nil)
return mutex
}()
func someFunc() {
pthread_mutex_lock(&mutex)
defer { pthread_mutex_unlock(&mutex) }
...
}
}

该代码在闭包中定义并初始化pthread_mutex_t,然后将返回的值分配给类属性。然后,它在几个功能中进行锁定和解锁,如图所示。

由于还应该调用pthread_mutex_destroy,这意味着互斥体内正在发生某种分配,这种分配可能引用也可能不引用原始值的地址。

实际上,互斥锁在一个地方初始化,然后存储在另一个地方。

问题是这样做是否安全或正确?

如果互斥初始化器需要参数怎么办?

private var mutex: pthread_mutex_t = {
var recursiveMutex = pthread_mutex_t()
var recursiveMutexAttr = pthread_mutexattr_t()
pthread_mutexattr_init(&recursiveMutexAttr)
pthread_mutexattr_settype(&recursiveMutexAttr, PTHREAD_MUTEX_RECURSIVE)
pthread_mutex_init(&recursiveMutex, &recursiveMutexAttr)
return recursiveMutex
}()

后一种方法让我觉得肯定是不正确的,因为当闭包崩溃时,其地址被传递到互斥对象中的属性存储将消失。

事实并非如此,此代码已损坏。

为了工作,pthread_mutex_t需要在类实例中原位初始化,并且永远不要复制出去。该类将需要公开锁/解锁方法,该方法对实例变量进行适当的操作。

值类型

注意,pthread_mutex_tpthread_rwlock_tos_unfair_lock是值类型,而不是引用类型。这意味着,如果你在它们上使用=,你就复制了一个。这很重要,因为这些类型无法复制!如果您复制pthread类型之一,则该副本将不可用,并且在尝试使用时可能会崩溃。

——作者Mike Ash,周五问答;A 2017-10-27:Locks,Thread Safety,and Swift:2017版

结账https://cocoawithlove.com/blog/2016/06/02/threads-and-mutexes.html

以下是pthread_mutex_t在Swift中的用法示例:https://github.com/mattgallagher/CwlUtils/blob/0bfc4587d01cfc796b6c7e118fc631333dd8ab33/Sources/CwlUtils/CwlMutex.swift#L60-L105

相关内容

  • 没有找到相关文章

最新更新