You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin使用synchronized实现对象锁及wait/notify调用报错问题咨询

Kotlin synchronized同步锁及wait/notify调用报错解决方案

报错核心原因

你写的synchronized函数本身用法是对的,报错的根本原因是:Kotlin的通用父类是Any,并没有默认携带Javajava.lang.Object的wait()、notify()、notifyAll()方法,只有将对象显式转为Java的Object类型才能调用这些方法。另外你对ReentrantLock的猜测有误,ReentrantLock完全可以实现自定义对象的加锁需求,搭配Condition的等待通知机制比原生wait/notify更灵活。

方案1:现有代码最小改动

你只需要把同步块内的wait()、notifyAll()改为显式用锁对象(你这里锁对象是this)调用,同时强转为JavaObject即可:

override fun run() {
    var active = false
    while (true) {
        while (queue.isEmpty()) {
            if (!running) {
                return
            }
            synchronized(this) {
                try {
                    active = false
                    // 改动点:显式用当前类对象调用wait,替换YourClassName为你实际的类名
                    (this@YourClassName as java.lang.Object).wait()
                } catch (e: InterruptedException) {
                    LogUtils.getLogger()
                        .log(Level.SEVERE, "There was a exception with SQL")
                    LogUtils.logThrowable(e)
                }
            }
        }
        if (!active) {
            con.refresh()
            active = true
        }
        val rec = queue.poll()
        con.updateSQL(rec.getType(), *rec.getArgs())
    }
}

/**
 * Adds new record to the queue, where it will be saved to the database.
 *
 * @param rec Record to save
 */
fun add(rec: Record) {
    synchronized(this) {
        queue.add(rec)
        // 改动点:显式用锁对象调用notifyAll
        (this as java.lang.Object).notifyAll()
    }
}

/**
 * Ends this saver's job, letting it save all remaining data.
 */
fun end() {
    synchronized(this) {
        running = false
        // 改动点:显式用锁对象调用notifyAll
        (this as java.lang.Object).notifyAll()
    }
}

方案2:Kotlin推荐写法(用ReentrantLock)

Kotlin更推荐用java.util.concurrent.locks包下的锁实现,代码更易读,也不需要强转类型:
首先在类内定义锁和对应的Condition:

private val lock = ReentrantLock()
private val queueNotEmpty = lock.newCondition()
@Volatile private var running = true
private val queue = ArrayDeque<Record>()

然后改写对应的方法,还可以用Kotlin标准库的Lock.withLock扩展函数简化加锁解锁逻辑,不用手动写finally释放锁:

override fun run() {
    var active = false
    while (true) {
        lock.withLock {
            while (queue.isEmpty()) {
                if (!running) {
                    return
                }
                active = false
                queueNotEmpty.await()
            }
        }
        
        if (!active) {
            con.refresh()
            active = true
        }
        val rec = queue.poll()
        con.updateSQL(rec.getType(), *rec.getArgs())
    }
}

fun add(rec: Record) {
    lock.withLock {
        queue.add(rec)
        queueNotEmpty.signalAll()
    }
}

fun end() {
    lock.withLock {
        running = false
        queueNotEmpty.signalAll()
    }
}

Kotlin synchronized正确用法补充

Kotlin的synchronized是顶层函数,通用语法为:

synchronized(你要加锁的任意对象) {
    // 同步代码块,同一时间只有一个线程能进入
}

这个逻辑和Java的synchronized关键字功能完全一致,没有区别。

内容的提问来源于stack exchange,提问作者Junhyung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 00:15:03