在 Swift 中移动互斥锁安全吗?

Is it safe to move a mutex in 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,然后将返回值赋给class属性。然后它在几个功能中锁定和解锁,如图所示。

由于还应该调用 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 需要在 class 实例中就地初始化,并且 从不 复制出来。 class 需要在实例变量上公开 lock/unlock 方法。

Value Types

Note that pthread_mutex_t, pthread_rwlock_t, and os_unfair_lock are value types, not reference types. That means that if you use = on them, you make a copy. This is important, because these types can't be copied! If you copy one of the pthread types, the copy will be unusable and may crash when you try to use it.

By Mike Ash, Friday Q&A 2017-10-27: Locks, Thread Safety, and Swift: 2017 Edition

查看 https://cocoawithlove.com/blog/2016/06/02/threads-and-mutexes.html

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