欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Swift?中的?Actors?使用及如何防止數(shù)據(jù)競(jìng)爭(zhēng)問題(示例詳解)

 更新時(shí)間:2023年06月06日 10:38:46   作者:Swift社區(qū)  
Swift中的Actors旨在完全解決數(shù)據(jù)競(jìng)爭(zhēng)問題,但重要的是要明白,很可能還是會(huì)遇到數(shù)據(jù)競(jìng)爭(zhēng),本文將介紹Actors是如何工作的,以及你如何在你的項(xiàng)目中使用它們,感興趣的朋友跟隨小編一起看看吧

前言

Actors 是 Swift 5.5 引入的一種并發(fā)編程模型,用于管理共享數(shù)據(jù)并提供數(shù)據(jù)訪問的安全性。Actors 使用異步消息傳遞來保護(hù)數(shù)據(jù),防止數(shù)據(jù)競(jìng)爭(zhēng)和其他并發(fā)問題。在這篇回答中,我將解釋 Actors 的基本原理,并提供一些示例代碼來說明其用法和如何防止數(shù)據(jù)競(jìng)爭(zhēng)。

Swift 中的 Actors 旨在完全解決數(shù)據(jù)競(jìng)爭(zhēng)問題,但重要的是要明白,很可能還是會(huì)遇到數(shù)據(jù)競(jìng)爭(zhēng)。本文將介紹 Actors 是如何工作的,以及你如何在你的項(xiàng)目中使用它們。

Actors 的基本原理

Actors 是并發(fā)編程中的一種實(shí)體,它封裝了一組相關(guān)的數(shù)據(jù)和操作,并且只能通過異步消息進(jìn)行訪問。每個(gè) Actor 在任意時(shí)刻只能執(zhí)行一個(gè)任務(wù),從而避免了數(shù)據(jù)競(jìng)爭(zhēng)。其他代碼通過向 Actor 發(fā)送異步消息來請(qǐng)求數(shù)據(jù)或執(zhí)行操作,Actor 在收到消息后逐個(gè)處理它們。

Actors 使用 async 和 await 關(guān)鍵字定義異步函數(shù)和等待異步結(jié)果,從而支持并發(fā)操作。每個(gè) Actor 中的數(shù)據(jù)都是私有的,只能通過 Actor 提供的方法進(jìn)行修改和訪問,以保證數(shù)據(jù)的一致性和安全性。

下面是一個(gè)簡(jiǎn)單的示例,展示了如何定義和使用 Actor:

actor Counter {
    private var value = 0
    func increment() {
        value += 1
    }
    func getValue() async -> Int {
        return value
    }
}
// 創(chuàng)建 Counter Actor 實(shí)例
let counter = Counter()
// 在異步任務(wù)中調(diào)用 Actor 方法
Task {
    await counter.increment()
    let result = await counter.getValue()
    print("Counter value: \(result)")
}

在上面的代碼中,Counter 是一個(gè)簡(jiǎn)單的 Actor,包含一個(gè)私有的 value 變量和兩個(gè)方法 increment 和 getValue。increment 方法用于增加 value 的值,getValue 方法用于獲取當(dāng)前的 value 值。

在異步任務(wù)中,我們創(chuàng)建了一個(gè) Counter 的實(shí)例 counter,并通過 await 關(guān)鍵字調(diào)用了 increment 和 getValue 方法。注意,在調(diào)用 Actor 的方法時(shí),我們使用了 await 關(guān)鍵字來等待異步操作完成,并確保在訪問和修改 Actor 數(shù)據(jù)時(shí)的安全性。

Actor 是引用類型,但與類相比仍然有所不同

Actor 是引用類型,簡(jiǎn)而言之,這意味著副本引用的是同一塊數(shù)據(jù)。因此,修改副本也會(huì)修改原始實(shí)例,因?yàn)樗鼈冎赶蛲粋€(gè)共享實(shí)例。你可以在我的文章Swift 中的 Struct 與 class 的區(qū)別中了解更多這方面的信息。

然而,與類相比,Actor 有一個(gè)重要的區(qū)別:他們不支持繼承。

Swift 中的 Actor 幾乎和類一樣,但不支持繼承。

不支持繼承意味著不需要像便利初始化器和必要初始化器、重寫、類成員或 openfinal 語句等功能。

然而,最大的區(qū)別是由 Actor 的主要職責(zé)決定的,即隔離對(duì)數(shù)據(jù)的訪問。

為什么會(huì)出現(xiàn)數(shù)據(jù)競(jìng)爭(zhēng)

數(shù)據(jù)競(jìng)爭(zhēng)是多線程/并發(fā)編程中常見的問題,它發(fā)生在多個(gè)線程同時(shí)訪問共享數(shù)據(jù),并且至少其中一個(gè)線程對(duì)該數(shù)據(jù)進(jìn)行了寫操作。當(dāng)多個(gè)線程同時(shí)讀寫共享數(shù)據(jù)時(shí),數(shù)據(jù)的最終結(jié)果可能會(huì)產(chǎn)生不確定性,導(dǎo)致程序出現(xiàn)錯(cuò)誤的行為。

數(shù)據(jù)競(jìng)爭(zhēng)發(fā)生的原因主要有以下幾個(gè)方面:

1、競(jìng)態(tài)條件(Race Condition):當(dāng)多個(gè)線程在沒有適當(dāng)同步的情況下并發(fā)地訪問共享數(shù)據(jù)時(shí),它們的執(zhí)行順序是不確定的。這可能導(dǎo)致數(shù)據(jù)的交錯(cuò)讀寫,從而導(dǎo)致數(shù)據(jù)的最終結(jié)果出現(xiàn)錯(cuò)誤。

2、缺乏同步:如果多個(gè)線程在沒有適當(dāng)?shù)耐綑C(jī)制的情況下訪問共享數(shù)據(jù),就會(huì)產(chǎn)生數(shù)據(jù)競(jìng)爭(zhēng)。例如,多個(gè)線程同時(shí)對(duì)同一個(gè)變量進(jìn)行寫操作,而沒有使用互斥鎖或其他同步機(jī)制來保證原子性。

3、共享資源的修改:當(dāng)多個(gè)線程同時(shí)對(duì)共享資源進(jìn)行寫操作時(shí),就會(huì)產(chǎn)生數(shù)據(jù)競(jìng)爭(zhēng)。如果沒有適當(dāng)?shù)耐綑C(jī)制來保護(hù)共享資源的一致性,就會(huì)導(dǎo)致數(shù)據(jù)競(jìng)爭(zhēng)。

4、可見性問題:多個(gè)線程可能具有各自的本地緩存或寄存器,這導(dǎo)致它們對(duì)共享數(shù)據(jù)的可見性存在延遲。當(dāng)一個(gè)線程修改了共享數(shù)據(jù),其他線程可能無法立即看到這個(gè)修改,從而導(dǎo)致數(shù)據(jù)競(jìng)爭(zhēng)。

數(shù)據(jù)競(jìng)爭(zhēng)可能導(dǎo)致程序出現(xiàn)各種問題,包括不確定的結(jié)果、崩潰、死鎖等。為了避免數(shù)據(jù)競(jìng)爭(zhēng),需要采取適當(dāng)?shù)牟l(fā)控制措施,例如使用鎖、互斥量、信號(hào)量等同步機(jī)制來保護(hù)共享數(shù)據(jù)的訪問,或者使用并發(fā)安全的數(shù)據(jù)結(jié)構(gòu)來代替共享數(shù)據(jù)。

在 Swift 中,引入了一些并發(fā)編程的機(jī)制,如 async/await 和 Actor,可以幫助開發(fā)者更容易地處理并發(fā)問題和避免數(shù)據(jù)競(jìng)爭(zhēng)。但仍需要開發(fā)者在編寫并發(fā)代碼時(shí)注意使用正確的同步機(jī)制和遵循最佳實(shí)踐,以確保數(shù)據(jù)的安全和正確性。

如何防止數(shù)據(jù)競(jìng)爭(zhēng)

Actors 通過限制同一時(shí)間只有一個(gè)任務(wù)可以訪問 Actor 中的數(shù)據(jù)來防止數(shù)據(jù)競(jìng)爭(zhēng)。這種限制確保了數(shù)據(jù)的一致性和線程安全性,而無需顯式使用鎖或其他同步機(jī)制。

Actors 還提供了數(shù)據(jù)的原子性訪問和修改操作。在 Actor 內(nèi)部,數(shù)據(jù)可以在異步環(huán)境中自由地修改,而不需要額外的同步操作。同時(shí),Actors 會(huì)保證 Actor 的內(nèi)部狀態(tài)在處理完一個(gè)消息之前不會(huì)被其他任務(wù)訪問,從而避免了并發(fā)問題。

在上面的示例中,我們可以看到在異步任務(wù)中通過 await 關(guān)鍵字調(diào)用 Counter 的方法。這樣做可以確保在不同的任務(wù)中對(duì) Counter 的訪問是串行的,從而避免了數(shù)據(jù)競(jìng)爭(zhēng)和其他并發(fā)問題。

Actors 是 Swift 中用于并發(fā)編程的一種模型,它通過異步消息傳遞來保護(hù)共享數(shù)據(jù),并防止數(shù)據(jù)競(jìng)爭(zhēng)。下面是一些闡述 Actors 的使用和防止數(shù)據(jù)競(jìng)爭(zhēng)的關(guān)鍵要點(diǎn):

1、定義 Actor:使用 actor 關(guān)鍵字來定義一個(gè) Actor 類,將要保護(hù)的數(shù)據(jù)和相關(guān)操作封裝在其中。例如:

actor MyActor {
    private var sharedData: Int = 0
    func performTask() {
        // 對(duì)共享數(shù)據(jù)進(jìn)行操作
    }
}

2、異步訪問:通過 async 和 await 關(guān)鍵字來標(biāo)記異步函數(shù)和等待異步結(jié)果。只有通過異步函數(shù)或方法訪問 Actor 中的數(shù)據(jù)才是安全的。例如:

actor MyActor {
    private var sharedData: Int = 0
    func performTask() async {
        sharedData += 1
        await someAsyncOperation()
        let result = await anotherAsyncOperation()
        // 對(duì)共享數(shù)據(jù)進(jìn)行操作
    }
}

3、 發(fā)送異步消息:通過在 Actor 實(shí)例上使用 await 關(guān)鍵字來發(fā)送異步消息,并調(diào)用 Actor 中的方法。這樣做可以確保對(duì) Actor 的訪問是串行的,從而避免了數(shù)據(jù)競(jìng)爭(zhēng)。例如:

let myActor = MyActor()
Task {
    await myActor.performTask()
}

4、數(shù)據(jù)保護(hù):由于 Actors 限制了同一時(shí)間只能執(zhí)行一個(gè)任務(wù),因此可以保證對(duì)共享數(shù)據(jù)的訪問是串行的,從而避免了數(shù)據(jù)競(jìng)爭(zhēng)。Actors 還提供了內(nèi)部狀態(tài)的保護(hù),確保在處理一個(gè)消息之前不會(huì)被其他任務(wù)訪問。

使用 async/await 訪問數(shù)據(jù)

在 Swift 中,使用 async/await 關(guān)鍵字來進(jìn)行異步訪問數(shù)據(jù)是一種安全且方便的方式,特別適用于訪問 Actor 中的共享數(shù)據(jù)。下面是一些示例代碼來說明如何使用 async/await 訪問數(shù)據(jù):

actor MyActor {
    private var sharedData: Int = 0
    func readData() async -> Int {
        return sharedData
    }
    func writeData(value: Int) async {
        sharedData = value
    }
}
// 創(chuàng)建 MyActor 實(shí)例
let myActor = MyActor()
// 異步讀取共享數(shù)據(jù)
Task {
    let data = await myActor.readData()
    print("Shared data: \(data)")
}
// 異步寫入共享數(shù)據(jù)
Task {
    await myActor.writeData(value: 10)
    print("Data written successfully")
}

在上面的示例中,readData 方法和 writeData 方法被標(biāo)記為 async,表示它們是異步的。通過 await 關(guān)鍵字,我們可以在異步任務(wù)中等待數(shù)據(jù)的讀取和寫入操作完成。

使用 await 關(guān)鍵字調(diào)用 readData 方法時(shí),任務(wù)會(huì)等待直到共享數(shù)據(jù)的讀取操作完成,并將結(jié)果返回。類似地,使用 await 關(guān)鍵字調(diào)用 writeData 方法時(shí),任務(wù)會(huì)等待直到共享數(shù)據(jù)的寫入操作完成。

需要注意的是,在使用 async/await 訪問數(shù)據(jù)時(shí),要確保訪問的方法或?qū)傩允钱惒降?。?duì)于 Actor 中的方法,可以在其聲明前加上 async 關(guān)鍵字,表示它們是異步的。對(duì)于屬性,可以將其聲明為異步的計(jì)算屬性。

防止不必要的暫停

在上面的例子中,我們正在訪問我們 Actor 的兩個(gè)不同部分。首先,我們更新吃食的雞的數(shù)量,然后我們執(zhí)行另一個(gè)異步任務(wù),打印出吃食的雞的數(shù)量。每個(gè) await 都會(huì)導(dǎo)致你的代碼暫停,以等待訪問。在這種情況下,有兩個(gè)暫停是有意義的,因?yàn)閮刹糠制鋵?shí)沒有什么共同點(diǎn)。然而,你需要考慮到可能有另一個(gè)線程在等待調(diào)用 chickenStartsEating,這可能會(huì)導(dǎo)致在我們打印出結(jié)果的時(shí)候有兩只吃食的雞。

為了更好地理解這個(gè)概念,讓我們來看看這樣的情況:你想把操作合并到一個(gè)方法中,以防止額外的暫停。例如,設(shè)想在我們的 actor 中有一個(gè)通知方法,通知觀察者有一只新的雞開始吃東西:

extension ChickenFeeder {
    func notifyObservers() {
        NotificationCenter.default.post(name: NSNotification.Name("chicken.started.eating"), object: numberOfEatingChickens)
    }
} 

我們可以通過使用 await 兩次來使用此代碼:

let feeder = ChickenFeeder()
await feeder.chickenStartsEating()
await feeder.notifyObservers() 

然而,這可能會(huì)導(dǎo)致兩個(gè)暫停點(diǎn),每個(gè) await 都有一個(gè)。相反,我們可以通過從 chickenStartsEating 中調(diào)用 notifyObservers 方法來優(yōu)化這段代碼:

func chickenStartsEating() {
    numberOfEatingChickens += 1
    notifyObservers()
} 

由于我們已經(jīng)在 Actor 內(nèi)有了同步的訪問,我們不需要另一個(gè)等待。這些都是需要考慮的重要改進(jìn),因?yàn)樗鼈兛赡軙?huì)對(duì)性能產(chǎn)生影響。

非隔離(nonisolated)訪問

在 Swift 中,非隔離(nonisolated)訪問是指在一個(gè)異步函數(shù)內(nèi)部訪問類、結(jié)構(gòu)體或枚舉的非隔離成員。異步函數(shù)默認(rèn)情況下是隔離的,這意味著在異步函數(shù)內(nèi)部只能訪問該類型的隔離成員。但有時(shí)候我們需要在異步函數(shù)中訪問非隔離成員,這時(shí)就可以使用非隔離訪問。

為了進(jìn)行非隔離訪問,需要使用 nonisolated 關(guān)鍵字來修飾訪問權(quán)限。例如,假設(shè)有一個(gè)類 MyClass,其中有一個(gè)非隔離成員屬性 value:

class MyClass {
    nonisolated var value: Int = 0
}

現(xiàn)在,我們可以在異步函數(shù)內(nèi)部訪問 MyClass 的 value 屬性:

func asyncFunction() async {
    let instance = MyClass()
    await doSomething(with: instance.value) // 非隔離訪問
}

需要注意以下幾點(diǎn):

1、非隔離訪問只能在異步函數(shù)內(nèi)部進(jìn)行。在同步環(huán)境下或其他異步函數(shù)內(nèi)部,仍然需要使用隔離訪問。

2、非隔離訪問是一種權(quán)限放寬的操作,因此需要謹(jǐn)慎使用。確保在異步函數(shù)中對(duì)非隔離成員的訪問是安全的,并且不會(huì)引入數(shù)據(jù)競(jìng)爭(zhēng)或其他問題。

3、非隔離訪問只適用于可變性為非 nonmutating 的成員,即對(duì)可修改的成員進(jìn)行訪問。對(duì)于可讀的非隔離成員,可以直接使用隔離訪問。

為什么在使用 Actors 時(shí)仍會(huì)出現(xiàn)數(shù)據(jù)競(jìng)爭(zhēng)?

當(dāng)在你的代碼中持續(xù)使用 Actors 時(shí),你肯定會(huì)降低遇到數(shù)據(jù)競(jìng)爭(zhēng)的風(fēng)險(xiǎn)。創(chuàng)建同步訪問可以防止與數(shù)據(jù)競(jìng)爭(zhēng)有關(guān)的奇怪崩潰。然而,你顯然需要持續(xù)地使用它們來防止你的應(yīng)用程序中出現(xiàn)數(shù)據(jù)競(jìng)爭(zhēng)。

在你的代碼中仍然可能出現(xiàn)競(jìng)爭(zhēng)條件,但可能不再導(dǎo)致異常。認(rèn)識(shí)到這一點(diǎn)很重要,因?yàn)锳ctors 畢竟被宣揚(yáng)為可以解決一切問題的工具。例如,想象一下兩個(gè)線程使用 await正確地訪問我們的 Actor 的數(shù)據(jù):

queueOne.async {
    await feeder.chickenStartsEating()
}
queueTwo.async {
    print(await feeder.numberOfEatingChickens)
} 

這里的競(jìng)爭(zhēng)條件定義為:“哪個(gè)線程將首先開始隔離訪問?”。所以基本上有兩種結(jié)果:

  • 隊(duì)列一在先,增加吃食的雞的數(shù)量。隊(duì)列二將打?。?
  • 隊(duì)列二在先,打印出吃食的雞的數(shù)量,該數(shù)量仍為:0

這里的不同之處在于我們?cè)谛薷臄?shù)據(jù)時(shí)不再訪問數(shù)據(jù)。如果沒有同步訪問,在某些情況下這可能會(huì)導(dǎo)致無法預(yù)料的行為。

總結(jié)

使用 async/await 關(guān)鍵字來訪問數(shù)據(jù)是 Swift 中一種安全且方便的方式。在訪問 Actor 中的共享數(shù)據(jù)時(shí),可以使用 async/await 關(guān)鍵字來標(biāo)記異步方法,并通過 await 關(guān)鍵字等待讀取和寫入操作的完成。這樣可以確保數(shù)據(jù)的訪問是線程安全的,并且能夠充分利用 Swift 提供的并發(fā)編程能力。

到此這篇關(guān)于Swift 中的 Actors 使用以及如何防止數(shù)據(jù)競(jìng)爭(zhēng)的文章就介紹到這了,更多相關(guān)Swift Actors 使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Swift中非可選的可選值類型處理方法詳解

    Swift中非可選的可選值類型處理方法詳解

    Optional是Objective-C沒有的數(shù)據(jù)類型,是蘋果引入到Swift語言中的全新類型,它的特點(diǎn)就和它的名字一樣:可以有值,也可以沒有值,當(dāng)它沒有值時(shí),就是nil。下面這篇文章主要給大家介紹了關(guān)于Swift中非可選的可選值類型處理方法的相關(guān)資料,需要的朋友可以參考下。
    2017-11-11
  • Ubuntu 16.04上安裝 Swift 3.0及問題解答

    Ubuntu 16.04上安裝 Swift 3.0及問題解答

    本文給大家分享的是在Ubuntu系統(tǒng)中安裝 Swift 3.0的方法和步驟,以及安裝過程中有可能遇到的問題的解答,這里推薦給小伙伴們,希望大家能夠喜歡
    2016-07-07
  • switch實(shí)現(xiàn)一個(gè)兩數(shù)的運(yùn)算代碼示例

    switch實(shí)現(xiàn)一個(gè)兩數(shù)的運(yùn)算代碼示例

    這篇文章主要介紹了switch實(shí)現(xiàn)一個(gè)兩數(shù)的運(yùn)算代碼示例,需要的朋友可以參考下
    2017-06-06
  • Swift?中的?Actors?使用及如何防止數(shù)據(jù)競(jìng)爭(zhēng)問題(示例詳解)

    Swift?中的?Actors?使用及如何防止數(shù)據(jù)競(jìng)爭(zhēng)問題(示例詳解)

    Swift中的Actors旨在完全解決數(shù)據(jù)競(jìng)爭(zhēng)問題,但重要的是要明白,很可能還是會(huì)遇到數(shù)據(jù)競(jìng)爭(zhēng),本文將介紹Actors是如何工作的,以及你如何在你的項(xiàng)目中使用它們,感興趣的朋友跟隨小編一起看看吧
    2023-06-06
  • Swift使用CoreData時(shí)遇到的一些填坑記錄

    Swift使用CoreData時(shí)遇到的一些填坑記錄

    這篇文章主要給大家記錄了在Swift使用CoreData時(shí)遇到的一些坑,以及介紹了CoreData在Swift 3.0中的一點(diǎn)改變,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。
    2017-12-12
  • 簡(jiǎn)單分析Swift語言的一些基本特征

    簡(jiǎn)單分析Swift語言的一些基本特征

    這篇文章主要介紹了Swift語言的一些基本特征,本文從各語言最基礎(chǔ)的類與對(duì)象等方面來講,需要的朋友可以參考下
    2015-07-07
  • Swift 3.1聊天界面鍵盤效果的實(shí)現(xiàn)詳解

    Swift 3.1聊天界面鍵盤效果的實(shí)現(xiàn)詳解

    這篇文章主要給大家介紹了Swift 3.1聊天界面鍵盤效果實(shí)現(xiàn)的相關(guān)資料,文中介紹的非常詳細(xì),相信對(duì)大家的學(xué)習(xí)或者工作具有一定的參考價(jià)值,需要的朋友們下面來一起看看吧。
    2017-04-04
  • Swift實(shí)現(xiàn)倒計(jì)時(shí)5秒功能

    Swift實(shí)現(xiàn)倒計(jì)時(shí)5秒功能

    這篇文章主要為大家詳細(xì)介紹了Swift實(shí)現(xiàn)倒計(jì)時(shí)5秒功能,在“登錄”和“注冊(cè)”頁(yè)面也有相似功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • Swift中的HTTP模擬測(cè)試示例詳解

    Swift中的HTTP模擬測(cè)試示例詳解

    這篇文章主要為大家介紹了Swift中的HTTP模擬測(cè)試示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Swift 3中使用FMDB遇到的問題與解決方法

    Swift 3中使用FMDB遇到的問題與解決方法

    相信大家都熟悉OC使用FMDB第三方庫(kù),進(jìn)行數(shù)據(jù)庫(kù)操作,增、刪、改、查,但最近在Swift 3中使用FMDB遇到了一些問題,下面這篇文章主要給大家介紹了關(guān)于在Swift 3中使用FMDB遇到的問題與解決方法,需要的朋友可以參考下。
    2017-07-07

最新評(píng)論