【问题标题】:A thread does not access synchronized block线程不访问同步块
【发布时间】:2012-08-13 11:41:08
【问题描述】:

我在生产代码中遇到了一个突然的问题,自过去 5 到 6 年以来就没有发生过。我有一个线程池,它最多生成 64 个线程,所有 64 个线程都读取一些数据并将其放入一个通用的Map 中以供进一步处理。

读取是由来自特定源的所有线程完成的,我已经验证数据确实是从源读取的,但是,一个特定的批次没有被放入Map。

这是一个代码sn-p(由于保密问题,不能放整个代码):

try {
   <read the data>
    .
    .
    <do processing>
    .
    .
    synchronized(glock) { //glock is a class attribute, Object glock = new Object[];
     map.put(<data that was read>);
     log.debug("bla bla bla")
    }
} catch(Throwable e) { 
     log.error("error") 
  }
  finally {
    log.debug("done")
 }

问题:特定线程未进入同步块,未放入映射,未打印 "bla bla bla",未打印 "error",但会打印 "done"。

我已经验证了一切...代码中没有任何变化,这个问题突然出现了。问题是,我不能放任何额外的日志,因为它是生产代码,没有得到所有客户的同意,但这是最后一部分。

有没有人遇到过类似的问题,或者对此有所了解?正在读取的数据非常庞大,有 6000 条记录,每条记录至少有 0f 30-40 列数据。

提前致谢。

编辑:捕捉 Throwable 而不是 Exception

【问题讨论】:

  • 代码中有try/finally吗?
  • 发布实际代码。您发布的内容几乎没有任何信息。
  • @AaronDigulla:为尝试而编辑....catch。打印“finally”中的内容,不会导致异常。
  • 我将从显而易见的开始: 1. 在 try 块内查找 return 语句。 2. 寻找未被catch 块捕获的异常(和errors)。
  • 没有足够的细节来解决您的问题。此外,一般来说,发布一个众所周知的算法不会损害您的 NDA。只是不要向我们发布您正在解析的 csv 文件。我不是律师

标签: java multithreading synchronized


【解决方案1】:

从您向我们展示的内容看来,

synchronized(glock){}

将数据放入地图时抛出异常,而不是打印“bla bla bla”。
打印“完成”是因为它位于 try 的 finally 块中。

【讨论】:

  • 代码可能会抛出Error; Errors 不是从 Exception 继承的,所以上面的代码没有捕捉到它们。这可能意味着在调用堆栈的某处,错误被吞没了。一种著名的Error 是AssertError
  • 如果synchronized(glock){}确实引发了异常,它不会进入catch(Throwable e)吗?
  • @AaronDigulla 但错误通常是一种不可恢复的讨厌行为,它会让自己以某种方式被人所知。
  • @AaronDigulla:已更新,我已验证,代码正在使用 Throwable。抱歉,错过了。
  • @SeanPatrickFloyd:我只希望可以,我无法调试,代码部署在 Unix 上,我在 SVN windows 中有代码库,无法调试和测试,只能依赖日志。我尝试在 QA 中重现该问题,但它在 QA 中运行完美。问题仅限于生产。
【解决方案2】:

您的代码有 99% 的可能性有问题。这意味着synchronized 块中的代码会引发异常,但您看不到它。

通常的罪魁祸首是:

  • 空的catch 块吞下异常(可以在代码的其他地方)
  • catch 块中记录器的异常日志配置,例如,将异常写入不同的日志文件
  • 由于某种原因,日志消息未按顺序写入(因此 ERROR 行不在您期望的位置)
  • 某些异常情况(如内存不足)加上弹性代码会阻止写入日志消息。地图可能需要惊人的内存量。
  • log 不是标准的 Java 记录器,而是其他东西。

您在虚拟机中发现错误或存在硬件问题的可能性很小(可能不是硬件问题。

如果一切都失败了,您将需要在生产环境中调试问题。当然,您的客户会反对;到那时,你会让他们决定哪个对他们更重要:一些规则,你不能调试代码或修复错误。

【讨论】:

  • 最后我们没有说服客户……他选择了额外的检查(在调用代码的 Unix 脚本中),如果发生这种情况,则使事件失败……并重新启动再次工作。
  • 如果可以,请检查脚本的早期运行是否创建了正确的结果。此类错误有时会导致数据库中的数据损坏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多