我有一個在不同執行緒之間常用的集合。在一個執行緒中,我需要添加專案、洗掉專案、檢索專案并遍歷專案串列。我正在尋找的是一個集合,只要這些方法中的任何一個已經被呼叫,它就會阻止對其任何讀/寫/洗掉方法的訪問。因此,如果一個執行緒檢索一個專案,另一個執行緒必須等到讀取完成才能從集合中洗掉一個專案。
Kotlin 似乎沒有提供這個。但是,我可以創建一個包裝類來提供我正在尋找的同步。Java 似乎確實提供了 synchronizedList 類,但從我讀到的內容來看,這實際上是為了阻止對單個方法的呼叫,這意味著沒有兩個執行緒可以同時洗掉一個專案,但一個可以洗掉,而另一個執行緒讀取一個專案(是我試圖避免的)。
還有其他解決方案嗎?
uj5u.com熱心網友回復:
一個包裝器,例如由synchronizedList
synchronize 回傳的包裝器,它使用包裝器本身作為鎖來同步對每個方法的呼叫。因此,一個執行緒將被阻止呼叫get(),比如說,而另一個執行緒當前正在呼叫put(). (這就是問題似乎要問的。)
但是,正如該方法的檔案所指出的那樣,這對保護呼叫序列沒有任何作用,例如在遍歷集合時可能會使用。如果另一個執行緒在您對 的呼叫之間更改了集合next(),那么任何事情都可能發生。(這就是我認為問題的真正意義所在!)
為了安全地處理這個問題,您的選擇包括:
- 手動同步。將每個對集合的呼叫序列包圍在一個與集合
synchronized同步的塊中,例如:
val list = Collections.synchronizedList(mutableListOf<String>())
// …
synchronized (list) {
for (i in list) {
// …
}
}
如果集合在您的控制之下,這很簡單,并且相對容易做到。但是如果你錯過了任何序列,那么你可能會得到意想不到的行為。此外,您需要保持序列簡短,以避免長時間保持鎖定并影響性能。
- 使用提供原語的并發集合實作,讓您在一次呼叫中完成所需的所有處理,避免迭代和其他序列。
對于地圖,Java 通過其ConcurrentMap介面和高性能實作(例如ConcurrentHashMap. 這些方法允許您在一次呼叫中迭代、更新單個或多個映射、搜索、減少和許多其他整個映射操作,從而避免任何并發問題。
對于集合(根據這個問題),您可以使用 a ConcurrentSkipListSet,或者您可以從 a 創建一個ConcurrentHashMapwith newKeySet()。
對于串列(根據這個問題),選項較少。(我認為并發串列不太常見。)如果您不需要隨機訪問,ConcurrentLinkedQueue可能就足夠了。或者,如果修改比迭代少得多,CopyOnWriteArrayList也可以作業。
包中還有許多其他并發類java.util.concurrent,因此非常值得仔細查看其中是否有任何一個更適合您的特定情況。
- 如果您有特殊要求,您可以撰寫自己的支持它們的集合實作。顯然,這是更多的作業,并且只有在上述方法都不能滿足您的要求時才值得。
總的來說,我認為值得退后一步,看看是否真的需要迭代。從歷史上看,在從 FORTRAN 到 BASIC 和 C 再到 Java 的命令式語言中,for回圈一直是選擇的工具(有時是唯一的結構)用于對資料集合進行操作——對于我們這些在這些語言上長大的人來說,這是我們本能地追求的東西。但是函式式編程范式提供了替代工具,因此在像 Kotlin 這樣提供其中一些工具的語言中,最好停下來問自己“我最終想在這里實作什么?” (通常我們想要的實際上是更新所有條目,或者映射到一個新結構,或者搜索一個元素,或者找到最大值——所有這些在 Kotlin 中都有比低級迭代更好的方法。)
畢竟,如果你可以告訴編譯器你想做什么,而不是如何去做,那么你的程式可能會更短,更容易閱讀和維護,讓你有更多的時間去思考更重要的事情!
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/442557.html
上一篇::app:compileDebugAndroidTestKotlingFAILED未解決的參考:className多模塊專案
