免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

SwiftArraycopy的線程安全問(wèn)題

    

創(chuàng)新互聯(lián)建站專(zhuān)注為客戶(hù)提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、外貿(mào)網(wǎng)站建設(shè)、東港網(wǎng)絡(luò)推廣、小程序開(kāi)發(fā)、東港網(wǎng)絡(luò)營(yíng)銷(xiāo)、東港企業(yè)策劃、東港品牌公關(guān)、搜索引擎seo、人物專(zhuān)訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)建站為所有大學(xué)生創(chuàng)業(yè)者提供東港建站搭建服務(wù),24小時(shí)服務(wù)熱線:13518219792,官方網(wǎng)址:m.newbst.com

Swift Array copy 的線程安全問(wèn)題

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

內(nèi)存地址

定義測(cè)試 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)
}

測(cè)試 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)行測(cè)試

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

結(jié)果

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

測(cè)試 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)行測(cè)試

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

結(jié)果

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

測(cè)試 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)行測(cè)試

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

結(jié)果

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

線程安全問(wèn)題

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

Int array 的錯(cuò)誤

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

Struct array 的錯(cuò)誤

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

Object array 的錯(cuò)誤

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

對(duì)于 Int array 和 struct array 來(lái)說(shuō),賦值時(shí)進(jìn)行了 copy,但這個(gè)步驟應(yīng)該不是原子操作,所以放入 async closure 會(huì)出錯(cuò)。對(duì)于 object array 來(lái)說(shuō),賦值過(guò)程雖然沒(méi)有進(jìn)行 copy,但是要改變?cè)瓉?lái)的 array 并且保持被賦值的對(duì)象不變,應(yīng)該也要進(jìn)行 copy;也就是說(shuō)在更新 array 時(shí)才進(jìn)行 copy。推測(cè)此時(shí)的 copy 也不是原子操作,所以放入 async closure 會(huì)出錯(cuò)。

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

文章名稱(chēng):SwiftArraycopy的線程安全問(wèn)題
本文地址:http://m.newbst.com/article6/isjjig.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站用戶(hù)體驗(yàn)網(wǎng)站建設(shè)品牌網(wǎng)站設(shè)計(jì)域名注冊(cè)定制網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)