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
相关产品推荐
相关产品推荐

