使用ConcurrentHashMap进行Kotlin并发,而无需使用锁即可检索和删除

时间:2020-07-03 19:12:51

标签: kotlin concurrency java.util.concurrent concurrenthashmap

我正在尝试了解ConcurrentHashMap,看看是否可以在不加任何锁的情况下利用它。我有ConcurrentHashMap,每天刚开始有很多书。

class Z {
    val books: ConcurrentHashMap<String, Int> = ConcurrentHashMap()
    
    fun addBook(book: String, numberOfBooks: Int) {
        books[book] = numberOfBooks
    }
 
    fun doSomething(book: String) {
        val numberOfBooks = books.remove(book)
    }
}

以上将是线程安全的。但是现在,如果我需要添加验证只是为了确保在初始化过程中没有两次添加该书,那么我需要添加一个synchronized块以确保我没有添加以下内容。

class Z {
    val books: ConcurrentHashMap<String, Int> = ConcurrentHashMap()
    val lock = Any()
    fun addBook(book: String, numberOfBooks: Int) {
        synchronized(lock) {
            val existingBook = books[book]
            if(existingBook!=null)
                println("Book exists, BEWARE!!")
            books[book] = numberOfBooks
        }
    }
 
    fun doSomething(book: String) {
        var numberOfBooks : Int? 
        synchronized(lock)
            numberOfBooks=books.remove(book)
    }
}

有没有更好的方法让我做到这一点。我讨厌添加synchronized块只是为了在其中放入日志语句。

1 个答案:

答案 0 :(得分:1)

您很幸运:Map接口有几种方法可以自动完成这种事情,因此ConcurrentHashMap中的线程安全方法也是如此。

在这种情况下,您甚至不需要任何奇异的东西,只需对put()方法进行显式调用,因为它会返回前一个值(如果没有,则返回[[:digit:]]{4}-$)。

因此,您只需调整第一个示例即可:

null

…无需任何同步即可完成您想要的操作。 (您失去了Kotlin的数组访问语法糖,但是在这里显然不值得考虑。)

其他可以自动完成复杂工作的方法包括compute()merge()putIfAbsent()replace()等。值得一看整个班级,这样您就可以发现它们有用的情况。如您所知,同步会带来巨大的性能损失,因此,如果在不牺牲安全性的情况下避免同步,那将是一个巨大的胜利。

相关问题