简体   繁体   中英

Is Swift's copy-on-write thread-safe?

Making an array or dictionary a value type by definition, but then actually copying it only when one reference to it tries to modify it is a lovely idea, but it makes me wary in a multi-queued/threaded context. I need to know:

Is Swift's copy-on-write capability thread-safe? eg: If I create an array on one queue and pass it to another queue, is it safe for either queue to modify it while the other might be reading or modifying it? Since by definition the copy was made when the array reference was passed into the second queue, can we assume that the Swift engineers did the right thing and implemented copy-on-write in a queue-safe way?

I found this old discussion of this, which seems authoritative, but in both directions! https://developer.apple.com/forums/thread/53488

Some credible voices say it's thread-safe, others say it isn't. I imagine that this may be because in some early version of Swift it was not, while perhaps in Swift 5 it is. Does anyone here know for sure for Swift 5?

Here's some sample code to illustrate the issue:

func func1()
{
    var strings1: [String] = ["A", "B", "C"]
    var strings2: [String] = strings1   // array not actually copied
    queue.async()
    {
        strings2.append("D")
    }

    print(strings1[0])    // is this reference thread-safe?
    strings1.append("E")  // is this modification thread-safe?
}

OK, since no one from Apple/Swift Inc is replying, I'll venture my best guess:

I imagine that when you have an Array value in swift, it's a reference to a reference to an NSArray or an NSMutableArray. (Yes, I know this is only true for class objects, but let's keep it simple here.) Without assigning a new value to your Array value, the lower-level reference can can be made to refer to a different NS-object by simple operations on it, such as appending or trimming. There is also a reference count attached to the underlying NS-object.

When you modify an Array, the first thing Swift does is check to see if the Swift reference is the only one to the underlying NS-object. If so, the NSArray is converted to an NSMutableArray if necessary and the modification takes place. If not, the NSArray is copied into an NSMutableArray, the modification takes place, and the lower-level Swift reference is changed to point to the new NS-object.

If this is indeed the process that Copy on Write follows, and if we can assume that the reference count mechanism, and the retain/release system is thread-safe, then I would say that Copy on Write IS thread-safe. Even if another thread is making the modification, as described above, since it's modifying a copy that IT just made, it shouldn't alter the original array at all.

If you know for sure that anything I've written is incorrect, or if you know other information pertinent to this issue, PLEASE share it here. This issue is far too important to leave to "It should just work" status. :-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM