I've read about Copy-on-Write concept for optimization in Arrays
and other data structures in Swift
.
What I want to know is how Copy-on-Write works in a multi-threaded environment.
let arr1 = [1, 2, 3, 4]
let arr2 = arr1
arr1.withUnsafeBytes { print("arr1:", $0.baseAddress) } //0x000060000007ee60
arr2.withUnsafeBytes { print("arr2:", $0.baseAddress) } //0x000060000007ee60
DispatchQueue.global(qos: .default).async {
let arr3 = arr1
arr3.withUnsafeBytes { print("arr3:", $0.baseAddress) } //0x000060000007ee60
}
In the above code, arr1
and arr2
have same addresses initially as expected in copy-on-write
. But, arr3
also shares the same memory as arr1
and arr2
although it is executed on a different thread.
As far as I know, each thread has different stack allocation. Then why arr3
is still sharing the same location?
You're not looking at the addresses of the arrays. You're looking at the addresses of the internal backing storage of the arrays, which is shared and heap-allocated.
If you want to look at the addresses of the stack-allocated array container (the part that points to the backing storage), then you meant this:
var arr1 = [1, 2, 3, 4]
var arr2 = arr1
withUnsafePointer(to: &arr1) { print("arr1:", $0) }
withUnsafePointer(to: &arr2) { print("arr2:", $0) }
DispatchQueue.global(qos: .default).async {
let arr3 = arr1
withUnsafePointer(to: arr3) { print("arr3:", $0) }
}
// =>
arr1: 0x0000000122d671e0 // local stack
arr2: 0x0000000122d671e8 // local stack (next address)
arr3: 0x0000700000e48d10 // heap
I believe this is the kind of result you were expecting.