Kotlinsynchronized()是否不锁定基本类型?

class Notification(val context: Context, title: String, message: String) {
    private val channelID = "TestMessages"

    companion object ID {
        var s_notificationID = -1
    }

    init {
        var notificationID = -1
        synchronized(s_notificationID) {
            if (++s_notificationID == 0)
                createNotificationChannel()
            notificationID = s_notificationID
        }

以上是从两个线程同时调用的。中的断点createNotificationChannel()清楚地表明有时s_notificationID等于 1。

但是,如果我更改
synchronized(s_notificationID)
synchronized(ID)
那么它似乎锁定得很好。

synchronized() 是否不锁定基本类型?如果是这样,为什么要编译?

回答

查看生成的 JVM 字节码表明该ID示例看起来像

synchronized(ID) { ... }

这是你所期望的。然而,这个s_notificationID例子看起来更像

synchronized(Integer.valueOf(s_notificationID)) { ... }

在 Java 中,我们只能同步对象,而不能同步原语。Kotlin 基本上消除了这种区别,但看起来您已经找到了一个实现仍然渗透的地方。由于s_notificationIDintJVM 而言是一个(因此,不是对象)但synchronized需要一个对象,因此 Kotlin 足够“聪明”,可以Integer.valueOf按需包装值。对您来说不幸的是,这会产生非常不一致的结果,因为

此方法将始终缓存 -128 到 127(含)范围内的值,并且可能缓存此范围之外的其他值。

因此,对于较小的数字,这可以保证锁定内存中您无法控制的某些缓存对象。对于大型对象,它可能是一个新对象(因此总是未锁定),或者它可能会再次出现在您手中的缓存对象上。

这里的教训似乎是:不要同步原始类型。


以上是Kotlinsynchronized()是否不锁定基本类型?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>