真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

SwiftArraycopy的線程安全問題-創(chuàng)新互聯(lián)

成都創(chuàng)新互聯(lián)公司專注于調(diào)兵山企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站開發(fā),商城網(wǎng)站開發(fā)。調(diào)兵山網(wǎng)站建設(shè)公司,為調(diào)兵山等地區(qū)提供建站服務(wù)。全流程按需設(shè)計(jì)網(wǎng)站,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)

Swift Array copy 的線程安全問題

NSArray 繼承自 NSObject,屬于對象,有 copy 方法。Swift 的 Array 是 struct,沒有 copy 方法。把一個 Array 變量賦值給另一個變量,兩個變量的內(nèi)存地址相同嗎?與此相關(guān)的有多線程安全問題。本文探究這兩個問題。

內(nèi)存地址

定義測試 class 和 struct

class MyClass {         var intArr = [Int]()    var structArr = [MyStructElement]()    var objectArr = [MyClassElement]() }struct MyStructElement {}class MyClassElement {}

定義輸出內(nèi)存地址的 closure

let memoryAddress: (Any) -> String = {    guard let cVarArg = $0 as? CVarArg else { return "Can not find memory address" }    return String(format: "%p", cVarArg) }

測試 Int array

private func testIntArr() {    print(#function)         let my = MyClass()    for i in 0...10000 {         my.intArr.append(i)     }    print("Before arr address:", memoryAddress(my.intArr))             // Copy Array is NOT thread safe     let arr = my.intArr // If move this into async closure, crash     print("Temp   arr address:", memoryAddress(arr)) // Copy. Address different from my.intArr     DispatchQueue.global().async {        var sum = 0         for i in arr {             sum += i         }        print("Sum:", sum) // 0 + 1 + ... + 10000 = 50005000     }          my.intArr.removeAll()    for _ in 0...10000 {         my.intArr.append(0)     }    print("After  arr address:", memoryAddress(my.intArr)) // New address}

在 view controller 中進(jìn)行測試

override func viewDidLoad() {    super.viewDidLoad()         for _ in 0...1000 {         testIntArr()     } }

結(jié)果

Swift Array copy 的線程安全問題

Int array 的內(nèi)存地址不同,賦值過程發(fā)生了 copy。

測試 struct array

private func testStructArr() {    print(#function)         let my = MyClass()    for _ in 0...10000 {         my.structArr.append(MyStructElement())     }    print("Before arr address:", memoryAddress(my.structArr))         // Copy Array is NOT thread safe     let arr = my.structArr // If move this into async closure, crash     print("Temp   arr address:", memoryAddress(arr)) // Copy. Address different from my.structArr     DispatchQueue.global().async {        var sum = 0         for _ in arr {             sum += 1         }        print("Sum:", sum) // 10001     }              my.structArr.removeAll()    for _ in 0...10000 {         my.structArr.append(MyStructElement())     }    print("After  arr address:", memoryAddress(my.structArr)) // New address}

在 view controller 中進(jìn)行測試

override func viewDidLoad() {    super.viewDidLoad()         for _ in 0...1000 {         testStructArr()     } }

結(jié)果

Swift Array copy 的線程安全問題

Struct array 的內(nèi)存地址不同,賦值過程發(fā)生了 copy。

測試 Object array

private func testObjectArr() {    print(#function)         let my = MyClass()    for _ in 0...10000 {         my.objectArr.append(MyClassElement())     }    print("Before arr address:", memoryAddress(my.objectArr))         // Copy Array is NOT thread safe     let arr = my.objectArr // If move this into async closure, crash     print("Temp   arr address:", memoryAddress(arr)) // Not copy. Same as my.objectArr     DispatchQueue.global().async {        var sum = 0         for _ in arr {             sum += 1         }        print("Sum:", sum) // 10001     }              my.objectArr.removeAll()    for _ in 0...10000 {         my.objectArr.append(MyClassElement())     }    print("After  arr address:", memoryAddress(my.objectArr)) // New address}

在 view controller 中進(jìn)行測試

override func viewDidLoad() {    super.viewDidLoad()         for _ in 0...1000 {         testObjectArr()     } }

結(jié)果

Swift Array copy 的線程安全問題

一個 object array 變量賦值給另一個變量,兩個變量的內(nèi)存地址相同,也就是說沒有 copy。原來的 array 改變后,內(nèi)存地址改變,但不影響被賦值的變量。

線程安全問題

以上的寫法是不會報(bào)錯的。如果把 array 的賦值寫入 async closure,就會報(bào)錯。多試幾次,會有不同的錯誤。

Int array 的錯誤

DispatchQueue.global().async {    let arr = my.intArr // 在這里賦值會報(bào)錯     var sum = 0     for i in arr {         sum += i     }    print("Sum:", sum) }

Swift Array copy 的線程安全問題

Swift Array copy 的線程安全問題

Swift Array copy 的線程安全問題

Struct array 的錯誤

DispatchQueue.global().async {    let arr = my.structArr // 在這里賦值會報(bào)錯     var sum = 0     for _ in arr {         sum += 1     }    print("Sum:", sum) }

Swift Array copy 的線程安全問題

Swift Array copy 的線程安全問題

Object array 的錯誤

DispatchQueue.global().async {    let arr = my.objectArr // 在這里賦值會報(bào)錯     var sum = 0     for _ in arr {         sum += 1     }    print("Sum:", sum) }

Swift Array copy 的線程安全問題

Swift Array copy 的線程安全問題

對于 Int array 和 struct array 來說,賦值時進(jìn)行了 copy,但這個步驟應(yīng)該不是原子操作,所以放入 async closure 會出錯。對于 object array 來說,賦值過程雖然沒有進(jìn)行 copy,但是要改變原來的 array 并且保持被賦值的對象不變,應(yīng)該也要進(jìn)行 copy;也就是說在更新 array 時才進(jìn)行 copy。推測此時的 copy 也不是原子操作,所以放入 async closure 會出錯。

Array 的賦值過程是否進(jìn)行 copy,與其中的元素類型有關(guān)。如果 array 的元素是 Int、struct 等,在賦值時就 copy。如果 array 的元素是 object,在賦值時不 copy,賦值后在更新其中一個 array 變量時才 copy。Array 的 copy 是線程不安全的。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。


網(wǎng)頁名稱:SwiftArraycopy的線程安全問題-創(chuàng)新互聯(lián)
文章轉(zhuǎn)載:http://weahome.cn/article/jiohi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部