繁体   English   中英

Kotlin中的并发

[英]Concurrency in Kotlin

我有一个类,该类具有由多个线程编写的可为空的变量,例如

class A {
    var s: String? = null //var accessed by multiple threads

    fun doStuff() {
        if (s != null) {
            //not safe
        }
    }
}

为了解决这个问题,我通常会像这样制作一个不变的副本

class A {
    var s: String? = null //var accessed by multiple threads

    fun doStuff() {
        val sCopy = s
        if (sCopy != null) {
            //safe now
        }
    }
}

我了解了诸如volatile,synchronized等并发工具,但是我不擅长多线程,但我不知道该如何处理它,而且我敢肯定,比创建不可变的值有更好的方法来实现这一点,您将如何做? ?

在这些情况下,您可以简单地重用Java工具。

对于大多数简单情况,您将创建一个对象(可以是任何类型)用作锁,并在每次访问状态时都使用该锁。 有一个synchronized函数,甚至可以让您直接返回一个值:

val anyLock = Any()
fun syncWithArbitraryObjTest(): Int = synchronized(anyLock) { 123 }

需要注意的是synchronized在科特林函数返回一个值。 这使其比Java的synced关键字更强大。 从技术上讲,只要您为需要彼此synchronized所有相关代码块使用同一对象,就不会锁定哪个对象。

如果选择使用特定的Lock对象,例如ReentrantLock的实例,则可以使用withLock代替:

val lock = ReentrantLock()
fun syncWithLockTest(): Int = lock.withLock { 123 }

最后但并非最不重要的,你的代码val sCopy = s是没有副本s ,它只是一个第二个变量指向同一个对象; 此代码并不安全。

您需要将写入和读取锁定到变量,如下所示:

class A {
    var s: String? = null //var accessed by multiple threads
     set(s) {
         synchronized(this) {
             field = s
         }
    }

    fun doStuff() {
        synchronized(this) {
            //safe now    
        }
    }
}

您需要在setter中进行同步,因为否则线程在doStuff中时,该值可能会被覆盖。

尽管通常最好避免多个线程可以写入同一变量的情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM