在Swift中,当两个线程获取并设置非线程安全属性时会发生什么?

时间:2022-11-22 20:58:07

Take this code for example:

以此代码为例:

struct MascotProvider {
    private static var _mascot: MascotType?
    static var mascot: MascotType {
        get {
            if _mascot == nil { _mascot = Mascot() }
            return _mascot!
        }
        set { _mascot = newValue }
    }
}

This code is not thread-safe because if _mascot is nil and two threads try to get mascot, two instances of Mascot will be instantiated. But which one will be returned? Is it deterministic?

此代码不是线程安全的,因为如果_mascot为nil并且两个线程尝试获取吉祥物,则将实例化两个Mascot实例。但哪一个会被退回?这是确定性的吗?

Further, what happens when thread X gets and then thread Y sets before X's get has finished initializing/returning? What exactly is happening in this case? What gets returned to X? I'm sure I've seen a bad access error occur in the past (I swear!), but can't reproduce it now.

此外,在X的get获得完成初始化/返回之前,当线程X获得然后线程Y设置时会发生什么?在这种情况下究竟发生了什么?什么回到X?我确定我在过去发现了一个糟糕的访问错误(我发誓!),但现在无法重现它。

Can someone provide a step by step breakdown of what's happening?

有人可以逐步分解正在发生的事情吗?

1 个解决方案

#1


1  

But which one will be returned? Is it deterministic?

但哪一个会被退回?这是确定性的吗?

Whichever one is assigned to _mascot last. It's indeterministic

无论最后一个被分配给_mascot。这是不确定的

Having a set occur during the middle of a get should fine. IIRC, assignment to pointers is atomic, so it's not like the _mascot will ever be in an inconsistent combination of an old and new value. It'll be either the full old value, or the full new value (and its indeterministic as to which it is).

在一个get中间出现一组应该没问题。 IIRC,对指针的赋值是原子的,所以它不像_mascot将永远处于旧值和新值的不一致组合中。它将是完整的旧值或全新值(以及它的不确定性)。

#1


1  

But which one will be returned? Is it deterministic?

但哪一个会被退回?这是确定性的吗?

Whichever one is assigned to _mascot last. It's indeterministic

无论最后一个被分配给_mascot。这是不确定的

Having a set occur during the middle of a get should fine. IIRC, assignment to pointers is atomic, so it's not like the _mascot will ever be in an inconsistent combination of an old and new value. It'll be either the full old value, or the full new value (and its indeterministic as to which it is).

在一个get中间出现一组应该没问题。 IIRC,对指针的赋值是原子的,所以它不像_mascot将永远处于旧值和新值的不一致组合中。它将是完整的旧值或全新值(以及它的不确定性)。