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

Mic*_*ong 1 concurrency pthreads 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) }
        ...
    }

}
Run Code Online (Sandbox Code Playgroud)

该代码在闭包内定义并初始化 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
     }()
Run Code Online (Sandbox Code Playgroud)

后者让我觉得绝对是不正确的,因为当闭包崩溃时,其地址传递到互斥体的属性存储将消失。

Ale*_*ica 6

事实并非如此,这段代码已被破坏。

\n

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

\n
\n

值类型

\n

请注意pthread_mutex_t, 、pthread_rwlock_t、 和os_unfair_lock是值类型,而不是引用类型。这意味着如果您对它们使用=,您就会复制一份。这很重要,因为这些类型无法复制!如果您复制其中一种 pthread 类型,则该副本将无法使用,并且在您尝试使用它时可能会崩溃。

\n
\n

\xe2\x80\x93作者:Mike Ash,星期五问答 2017 年 10 月 27 日:锁、线程安全和 Swift:2017 版

\n

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

\n

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

\n