1

我正在对 Java 中的事件回调处理框架进行压力测试,该框架在可能的情况下大量使用并发,因此在可能发生数据竞争时使用同步方法和语句。在一个名为 testDispatchWorstCase 的单元测试中,将同时启动 100 到 500 个线程,每个线程都使用同步语句调用方法,这些语句利用一个名为 MasterSemaphore 的控制器对象的监视器。使用 100 个线程进行测试时,有时一切正常,有时我在一个或多个同步语句和/或方法中遇到 stackoverflow 异常。在使用 500 个线程进行测试时,我几乎总是在一个或多个同步语句和/或方法中遇到 stackoverflow 异常。

MasterSemaphore 提供了用于锁定同步语句的监视器,还提供了一些事件处理方法,这些方法被调用来协调各个线程对资源的访问。鉴于此,我想也许使用 MasterSemaphore 的成员对象,它没有其他职责,因为监视器提供者会解决问题——不幸的是,这只会导致死锁;数百个线程在 Eclipse 的调试器线程视图中停留在“监视器”状态并永远保持这种状态。我的问题如下:

  1. 对象的监视器如何存储和跟踪对该监视器锁定的线程的引用?

  2. 为什么我在使用 MasterSemaphore 的成员对象作为监视器提供程序时遇到了死锁?我需要在同步语句中显式调用 wait...notifyAll 吗?

  3. 当数百个线程受制于一个对象的监视器锁时,什么可能导致同步语句中的堆栈溢出?

堆栈跟踪是:

01-02 07:47:44.910 27698 27842 E AndroidRuntime: FATAL EXCEPTION: HPCHead Spawned 
Thread #24

01-02 07:47:44.910 27698 27842 E AndroidRuntime: java.lang.StackOverflowError

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at   
java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:147)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
java.lang.IntegralToString.convertInt(IntegralToString.java:209)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
java.lang.IntegralToString.appendInt(IntegralToString.java:173)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
java.lang.StringBuilder.append(StringBuilder.java:139)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
java.lang.Thread.toString(Thread.java:1098)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
addRegistrantForCallback_PrefabEventHandling(MasterSemaphore.java:2524)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterEventHandler$EventIDFreedHandler.
onUpdateNeeded(MasterEventHandler.java:221)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at     
com.hdradio.hdradiomanagerjc.hpc.CallbackDataRecord.
postToQueueHead(CallbackDataRecord.java:107)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
onFinishedEventProcessing(MasterSemaphore.java:1219)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
addRegistrantForCallback_PrefabEventHandling(MasterSemaphore.java:2597)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterEventHandler$EventIDFreedHandler.
onUpdateNeeded(MasterEventHandler.java:221)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.CallbackDataRecord.
postToQueueHead(CallbackDataRecord.java:107)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
onFinishedEventProcessing(MasterSemaphore.java:1219)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
addRegistrantForCallback_PrefabEventHandling(MasterSemaphore.java:2597)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterEventHandler$EventIDFreedHandler
.onUpdateNeeded(MasterEventHandler.java:221)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.CallbackDataRecord.
postToQueueHead(CallbackDataRecord.java:107)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
onFinishedEventProcessing(MasterSemaphore.java:1219)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
addRegistrantForCallback_PrefabEventHandling(MasterSemaphore.java:2597)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterEventHandler$EventIDFreedHandler.
onUpdateNeeded(MasterEventHandler.java:221)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.CallbackDataRecord.
postToQueueHead(CallbackDataRecord.java:107)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
onFinishedEventProcessing(MasterSemaphore.java:1219)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
addRegistrantForCallback_PrefabEventHandling(MasterSemaphore.java:2597)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterEventHandler$EventIDFreedHandler.
onUpdateNeeded(MasterEventHandler.java:221)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.CallbackDataRecord.
postToQueueHead(CallbackDataRecord.java:107)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
onFinishedEventProcessing(MasterSemaphore.java:1219)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
addRegistrantForCallback_PrefabEventHandling(MasterSemaphore.java:2597)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterEventHandler$EventIDFreedHandler.
onUpdateNeeded(MasterEventHandler.java:221)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.CallbackDataRecord.
postToQueueHead(CallbackDataRecord.java:107)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
onFinishedEventProcessing(MasterSemaphore.java:1219)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
addRegistrantForCallback_PrefabEventHandling(MasterSemaphore.java:2597)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterEventHandler$EventIDFreedHandler.
onUpdateNeeded(MasterEventHandler.java:221)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.CallbackDataRecord.
postToQueueHead(CallbackDataRecord.java:107)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
onFinishedEventProcessing(MasterSemaphore.java:1219)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
addRegistrantForCallback_PrefabEventHandling(MasterSemaphore.java:2597)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterEventHandler$EventIDFreedHandler.
onUpdateNeeded(MasterEventHandler.java:221)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.CallbackDataRecord.
postToQueueHead(CallbackDataRecord.java:107)

01-02 07:47:44.910 27698 27842 E AndroidRuntime:    at 
com.hdradio.hdradiomanagerjc.hpc.MasterSemaphore.
onFinishedEventProcessing(MasterSemaphore.java:1219)
4

1 回答 1

1

回答您的问题:

  1. 这是一篇描述如何使用对象监视器进行同步的文章

  2. 我不确定你为什么会陷入僵局。我需要查看更多代码才能提供帮助。不过,正如我在之前的评论中所说,您不需要使用wait'/notifyAllwhen using同步. The JVM handles all the locking and waiting automatically for you. Of course, this doesn't mean that you can't program yourself into a deadlock situation (that's actually pretty easy to do). Addingnotify() 调用不会解除死锁。

  3. 所以堆栈溢出问题来自递归调用堆栈,如下所示:

    ...

    MasterSemaphore.onFinishedEventProcessing(MasterSemaphore.java:1219) MasterSemaphore.addRegistrantForCallback_PrefabEventHandling(MasterSemaphore.java:2597) MasterEventHandler$EventIDFreedHandler.onUpdateNeeded(MasterEventHandler.java:221) CallbackDataRecord.postToQueueHead(CallbackDataRecord.java:107) MasterSemaphore.onFinishedEventProcessing(MasterSemaphore.java:1219)

所以onFinishedEventProcessing()被递归调用,这导致堆栈溢出。您应该看看为什么会发生这种情况(如果需要,添加一些日志记录)。

于 2013-05-07T08:05:25.967 回答