swift - GCD 真的是线程安全的吗?

标签 swift thread-safety grand-central-dispatch

我研究过 GCD 和线程安全。 在苹果文档中,GCD 是线程安全的,即多线程可以访问。 而且我了解了线程安全的含义,即每当多个线程访问某个对象时总是给出相同的结果。

我认为 Thread-Safe 和 GCD 的 Thread-Safe 的意思是不一样的,因为我测试了一些写在下面的案例来求和 0 到 9999。

当我多次执行下面的代码时,“something.n”的值不一样。 如果 GCD 是线程安全的,为什么“something.n”值不同?

我真的很困惑..你能帮我吗? 我真的很想掌握线程安全!!!

class Something {
    var n = 0
}
class ViewController: UIViewController {
    let something = Something()
    var concurrentQueue = DispatchQueue(label: "asdf", attributes: .concurrent)
    override func viewDidLoad() {
        super.viewDidLoad()
        let group = DispatchGroup()
        for idx in 0..<10000 {
            concurrentQueue.async(group: group) {
                self.something.n += idx
            }
        }
    
        group.notify(queue: .main ) {
            print(self.something.n)
        }
    }
}

最佳答案

你说:

I have studied GCD and Thread-Safe. In apple document, GCD is Thread-Safe that means multiple thread can access. And I learned meaning of Thread-Safe that always give same result whenever multiple thread access to some object.

他们说的是同一件事。只有当同时从不同线程调用它是安全的时,代码块才是线程安全的(并且这种线程安全是通过确保代码的关键部分不能在一个线程上同时在另一个线程上运行来实现的)线程)。

但让我们明确一点:Apple 并不是说​​如果您使用 GCD,您的代码就自动是线程安全的。是的,调度队列对象本身是线程安全的(即您可以安全地从您想要的任何线程调度到队列),但这并不意味着您自己的代码一定是线程安全的。如果一个人的代码同时从多个线程访问同一内存,则必须提供自己的同步以防止写入与任何其他访问同时进行。

Threading Programming Guide: Synchronization在 GCD 之前,Apple 概述了同步代码的各种机制。您还可以使用 GCD 串行队列进行同步。如果您使用并发队列,并且使用“屏障”进行写操作,则可以实现线程安全。见this answer的后半部分用于实现线程安全的各种方法。

但请注意,Apple 并未引入“线程安全”的不同定义。正如他们在上述 guide 中所说的那样:

When it comes to thread safety, a good design is the best protection you have. Avoiding shared resources and minimizing the interactions between your threads makes it less likely for those threads to interfere with each other. A completely interference-free design is not always possible, however. In cases where your threads must interact, you need to use synchronization tools to ensure that when they interact, they do so safely.

并且在 Concurrency Programming Guide: Migrating Away from Threads: Eliminating Lock-Based Code ,这是在引入 GCD 时发布的,Apple 说:

For threaded code, locks are one of the traditional ways to synchronize access to resources that are shared between threads. ... Instead of using a lock to protect a shared resource, you can instead create a queue to serialize the tasks that access that resource.

但他们并不是说您可以只使用 GCD 并发队列并自动实现线程安全,而是说通过谨慎和正确使用 GCD 队列,可以在不使用锁的情况下实现线程安全。


顺便说一句,Apple 提供了工具来帮助您诊断您的代码是否是线程安全的,即 Thread Sanitizer (TSAN)。参见 Diagnosing Memory, Thread, and Crash Issues Early .

关于swift - GCD 真的是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66515194/

相关文章:

ios - 使用 UIwebview 使用 swift 从库中附加照片

ios - Swift - 无法使用类型为 'JSON' 的参数列表调用类型为 '(Response<AnyObject, NSError>)' 的初始值设定项

linux - 线程安全的搜索和添加

iphone - 如何重写 [NSRunLoop runUntilDate :] to GCD code?

swift - 创建初始值为 0 的信号量会导致执行出现问题

ios - 具有附加依赖项的 UINavigationController 子类初始值设定项

swift - 如何设置结构的属性值?

java - 注入(inject) (@Inject) 字段是否已安全发布?

ruby - 重用 Ruby 中线程之间的连接/替换 Net::HTTP::Persistent

ios - 如何将拍摄的照片放到主线程?