Вы синхронизируете только геттер и сеттер, поэтому, когда вы начинаете использовать ссылку, попадающую в список, она уже разблокирована.
Kotlin имеет класс Mutex, доступный для блокировки манипуляций совместно используемого ресурса. изменчивый объект Mutex лучше, чем Java synchronized
, потому что он приостанавливается вместо блокировки потока сопрограммы.
Ваш пример будет плохим дизайном в реальном мире, потому что ваш класс публично предоставляет изменяемый список. Но, сделав это, сделайте хотя бы безопасным изменение списка:
class ListTest() {
private val myListMutex = Mutex()
private val myList = mutableListOf<String>()
init {
repeat(10000) {
myList.add("stuff: $it")
}
}
suspend fun modifyMyList(block: MutableList<String>.() -> Unit) {
myListMutex.withLock { myList.block() }
}
}
fun main() = runBlocking<Unit> {
val listTest = ListTest()
launch(Dispatchers.Default) {
delay(1L)
listTest.modifyMyList { it.remove("stuff: 54") }
}
launch {
listTest.modifyMyList { it.forEach { println(it) } }
}
}
Если вы не работаете с сопрограммами, вместо Mutex()
вы можете использовать Any
и вместо withLock
используйте synchronized (myListLock) {}
так же, как в Java, чтобы предотвратить одновременный запуск кода из синхронизированных блоков.