【问题标题】:What's the difference between thread safe and write/read safe? [duplicate]线程安全和写/读安全有什么区别? [复制]
【发布时间】:2019-03-12 08:29:59
【问题描述】:

在 iOS 中,原子只是保证写/读安全。不是线程安全的。有人说线程安全是更高级别的。我对他们的区别感到困惑。 w/r safe 有时可以用来实现线程安全吗? 而当原子不能保证
线程安全。为什么我们在多个线程中使用它?

【问题讨论】:

    标签: ios


    【解决方案1】:

    例如,考虑在 32 位处理器上运行的 64 位 long 整数类型。由于处理器一次只运行 32 位,更新 long 看起来像这样的伪程序集:

    mov %r1, [addr]
    mov %r2, [addr+4]
    

    如果变量以值 0 开头,而您尝试向其写入 0xffffffff,则执行可能会在这两条指令之间中断,而其他读取内存的代码读取值 0x0000ffff

    原子更新保证整个值以某种方式写入单个操作,因此虽然(因为它不是线程安全的)你不能保证另一个线程何时会看到更新的值,你保证无论何时它确实看到一个值,它不会被部分更新,而是一个完全正确的(即使可能是过时的)值。这个概念可以扩展到更复杂的相关数据类型。

    【讨论】:

    • 所以,它不能保证线程安全。原子可以用作实现线程安全的步骤。而线程安全是更高层次,我们使用锁
    【解决方案2】:

    atomic 保证仅在单个属性上独占执行,也就是说,您不能同时在对象上读取/写入单个属性。

    但是,atomic 不保证同一对象的两个不同属性可以同时独占访问/写入。

    为说明这一点而给出的最常见示例是具有firstNamelastName 属性的Person 类。

    let person = Person()
    
    // Thread 1
    person.firstName = "Name1"
    person.lastName = "LastName1"
    
    // Thread 2
    person.firstName = "Name2"
    person.lastName = "LastName2"
    

    在最坏的情况下,person 最终可能是Name1 LastName 2Name2 LastName1

    这是更高级别的线程安全发挥作用的地方,我使用锁定/解锁作为平台/语言特定锁定机制的占位符。

    let person = Person()
    
    // Thread 1
    lock(person)
    person.firstName = "Name1"
    person.lastName = "LastName1"
    unlock(person)
    
    // Thread 2
    lock(person)
    person.firstName = "Name2"
    person.lastName = "LastName2"
    unlock(person)
    

    通过这种锁定/解锁,我们保证在person 上设置firstNamelastName 一起执行。

    【讨论】:

    • 是的,从这个方面来说,线程安全是程序中事务的更高层次。 W/R safe 是一个普通且较低的级别,与我们程序中的逻辑没有关系。对吗?
    猜你喜欢
    • 2019-03-13
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-19
    相关资源
    最近更新 更多