Log4j:多线程调用是否同步?

我们遇到了一个有趣的问题,我们在对系统进行压力测试时注意到了这个问题。我们非常频繁地使用log4j(在JBOSS中)进行日志记录。这是一个天真的例子,我们一些日志记录

void someFunction()
{
Log.info("entered some function");
...

Log.info("existed some function");
}

现在我们注意到的有趣的事情是,如果我们针对这个函数启动100个线程;Log.info() 调用正在阻塞每个线程。这意味着线程 2 正在等待线程 1 完成“Log.info”调用。在线程100的情况下;它最终等待了很长时间。我们使用的是本机文件记录器。

这是一个已知问题吗?


答案 1

Log4J必须同步,否则您将在文件中看到交错和乱码的日志消息。但至少在 Logback 中,只有追加器是同步的,而不是整个日志记录消息(因此计算有效的日志级别、日志消息等是多线程的)。

但是,即使删除了同步,I/O 也将成为瓶颈,因为它本质上是单线程的。因此,请考虑减少日志记录量,因为文件访问速度较慢,而不是Log4J。

您可能还对 AsyncAppender 感兴趣,它可以在单个不同的线程中对日志记录消息进行排队。


答案 2

是的,log4j 使用多线程同步。有时并不完美。

我们遇到了一些性能下降,这是由于使用复杂的toString()方法争夺log4j锁甚至死锁引起的。

例如,请参阅 https://issues.apache.org/bugzilla/show_bug.cgi?id=24159https://issues.apache.org/bugzilla/show_bug.cgi?id=41214#c38

在我的另一个答案中的更多详细信息:log4j的生产设置文件?

我想这是自JBoss AS 6以来存在并切换到自定义日志管理器的原因之一。