我對我的代碼中的一些情況感到有點困惑。
private var state by synchronized<PlayerState>(Stopped()
val asStarted get() = state as? 開始
val asStopped get() = state as? 已停止
inner class Stopped : PlayerState {
fun start(bpm。BPM = BPM(), volume: Int? = null) {
狀態 = Started(bpm, volume)
}
}
想象一下,兩個執行緒正試圖執行player.asStopped?.start(),我在這里有問題嗎?我需要輸入這樣的東西嗎?
inner class Stopped 。PlayerState { : PlayerState
:PlayerState { :PlayerState
fun start(bpm。BPM = BPM(), volume: Int? = null) {
if(state is Started) return
state = Started(bpm, volume)
}
}
感謝您的幫助。
uj5u.com熱心網友回復:
你的擔心是對的。
你的第一個版本的代碼確實有一個競賽條件,因為兩個執行緒可以同時創建Started物件,然后設定它們。?一次只能有一個執行緒在執行設定器,但是第二個執行緒可以在第一個執行緒離開后立即進入設定器。
這在這里可能不是一個問題。?(synchronized delegate仍將防止訪問state的任何低級問題,例如看到部分構造的值。?而且看起來沒有其他狀態需要與你的state屬性相關聯,所以它不能進入不一致的狀態)。? 但是能夠啟動兩次可能不是好事!
我不知道該怎么做。
我不認為認為你的第二個版本的代碼會有任何執行緒問題,就像寫的那樣。?(如果它沒有 然而,它有點令人困惑,因為它使用了兩個獨立的鎖定機制( 我還懷疑這可能會導致周圍代碼中出現競賽條件。?一旦啟動,你的播放器能否再次停止??如果可以,那么 因此,我強烈要求對其進行重構,只使用一個鎖。
我不知道您的代碼所使用的 不過,這確實提出了一個關于設計的更廣泛的問題。為什么你的 解決這一設計問題幾乎肯定會使解決鎖定問題變得更加容易。
標籤:@Synchronized,那么它確實會出現檢查時間到使用時間的競賽條件。
@Synchronized方法鎖定Stopped物件,而by synchronized狀態有自己的鎖),而且很難遵循這些鎖可能的互動方式,即使在這個非常簡單的例子中。
stop() 方法將鎖定什么?如果是 Started 物件,那么這就是另一個鎖,而且我可以看到那里有一些競賽條件。
synchronized delegate。?如果它有某種測驗和設定、比較和交換或類似的功能,那么你可能能夠使用它來完成你所需要的東西。?否則,恐怕你最好還是放棄這個委托,自己去鎖。
Stopped類有一個start()方法?當然,啟動和停止的是player,而狀態只是對它的反映??因此,改變狀態根本不是對當前狀態的操作。
