有没有 vert.x 或者有关注 Java 虚拟线程的群

查看 26|回复 0
作者:byte10   
一、背景
最近使用 vert.x 在开发一个 java 程序,只所以用 vert.x 就是因为它比较适合开发这类的程序。但是异步编程开发起来实在不好维护。。实现也太麻烦了,实在是太复杂了。下单完还要判断是否成功,还有循环下单等,很多时候异步实现起来非常的不好实现和阅读。
二、引入虚拟线程
目前引入的虚拟线程遇到非常大的麻烦。一般一个 verticle 绑定一个 eventloop 线程,我把虚拟线程绑定 vert.x eventloop 的线程中,,这样每个 verticle 内使用的所有虚拟线程也是它们自己平台 eventloop 线程,也就是在 verticle 使用的所有虚拟线程和自己平台线程 都是同一个线程,所以理论也是线程安全的。目前遇到的是虚拟线程和它自己的平台线程在执行 log 日志输出的时候,就会遇到死锁。也就是虚拟线程和它自己的平台线程发生了竞争 log.info 的输出。
下面是异常日志:
Thread Thread[#63,vert.x-eventloop-thread-1,5,main] has been blocked for 10586 ms, time limit is 2000 ms
io.vertx.core.VertxException: Thread blocked
        at java.base/jdk.internal.misc.Unsafe.park(Native Method)
        at java.base/java.util.concurrent.locks.LockSupport.park(LockSupport.java:221)
        at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:754)
        at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:990)
        at java.base/java.util.concurrent.locks.ReentrantLock$Sync.lock(ReentrantLock.java:153)
        at java.base/java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:322)
        at ch.qos.logback.core.OutputStreamAppender.writeBytes(OutputStreamAppender.java:200)
        at ch.qos.logback.core.OutputStreamAppender.writeOut(OutputStreamAppender.java:193)
        at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:228)
        at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:102)
        at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:85)
        at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)
        at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:272)
        at ch.qos.logback.classic.Logger.callAppenders(Logger.java:259)
        at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:426)
使用 jstack -l pid 检查确实一直 block 中.
LockSupport.class
public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        try {
            if (t.isVirtual()) {
                VirtualThreads.park();
            } else {
                U.park(false, 0L);
            }
        } finally {
            setBlocker(t, null);
        }
    }
由于 verticle 可能是很多个,可能会绑定到同一个 eventloop 线程,所以很难从代码上比较难规避。
一般使用 ReentrantLock.lock 产生死锁的情况是什么原因呢?个人感觉跟 vert.x 关系不大,应该是虚拟线程的问题。也不确定是否 ReentrantLock.lock 的问题,头大。
您需要登录后才可以回帖 登录 | 立即注册

返回顶部