kotlin - Kotlin synchronized() 是否不锁定基本类型?

标签 kotlin

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_notificationIDint就 JVM 而言(因此,不是对象)而是 synchronized期望一个对象,Kotlin 足够“聪明”,可以将值包装在 Integer.valueOf 中一经请求。对您来说不幸的是,这会产生非常不一致的结果,because

This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.


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

关于kotlin - Kotlin synchronized() 是否不锁定基本类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68423781/

相关文章:

Java 与 Kotlin 泛型

gradle - 如何使 compileKotlin 依赖于 compileJava in gradle

generics - Kotlin 编译器的类型推断无法选择调用哪个方法(泛型有歧义)

java - Zip ByteArray 解压返回 null 但输入流有效

java - 在 try/catch 之前初始化非空类型变量

android - 无尽的 RecyclerView 数据加载逻辑在所有设备上并不一致

android - 如何立即开始执行 Kotlin Coroutine

android - 在 Kotlin 中将分钟添加到时间格式

android - Android:布局数据变量:XML文件无法使用ViewModel类

android - 调用 requiresPermission 注释方法时缺少权限提示