gpt4 book ai didi

java - ReentrantLock 在同一个线程中被神秘地解锁,即使没有其他线程正在访问它

转载 作者:行者123 更新时间:2023-12-01 12:11:23 26 4
gpt4 key购买 nike

我有一些我认为非常简单的代码:

public int internalWrite(byte[] data, int offset, int size) throws InterruptedException {
lock.lockInterruptibly();
try {
if (state == State.RELEASED) throw new TrackReleasedException();
return track.write(data, offset, size, AudioTrack.WRITE_NON_BLOCKING);
} finally {
if (!lock.isHeldByCurrentThread()) {
Log.e("phonographnative", "internalWrite() lock is not held by current thread! " + Thread.currentThread());
} else lock.unlock();
}
}
lockfair ReentrantLock,但非 fair 也会出现此问题一。 track是一个 Android AudioTrack;它的 write方法主要是 native 代码(但与线程无关)。它无权访问 lock反正。在实践中实际上从未抛出异常(在调查此行为时也从未抛出异常)。发生的情况是,非常可重复地(稍后会详细介绍),锁将在同一个线程中神秘地解锁,从而导致出现日志消息。以前,当我没有进行此检查时,预计会抛出 IllegalMonitorStateException。在这种情况发生几次后,就会出现 java.lang.AssertionError: Attempt to repark ,在锁的代码本身内。一些示例性的日志输出:
2019-03-20 12:20:37.428 8097-8181/com.kabouzeid.gramophone.debug E/phonographnative: internalWrite() lock is not held by current thread! Thread[phonographnative-decoding-65308.0,5,main]
2019-03-20 12:20:37.428 8097-8184/com.kabouzeid.gramophone.debug E/phonographnative: internalWrite() lock is not held by current thread! Thread[phonographnative-decoding-65308.0,5,main]
2019-03-20 12:20:37.428 8097-8181/com.kabouzeid.gramophone.debug E/phonographnative: internalWrite() lock is not held by current thread! Thread[phonographnative-decoding-65308.0,5,main]
2019-03-20 12:20:37.428 8097-8184/com.kabouzeid.gramophone.debug E/phonographnative: internalWrite() lock is not held by current thread! Thread[phonographnative-decoding-65308.0,5,main]
2019-03-20 12:20:37.430 8097-8184/com.kabouzeid.gramophone.debug E/AndroidRuntime: FATAL EXCEPTION: phonographnative-decoding-65308.0
Process: com.kabouzeid.gramophone.debug, PID: 8097
java.lang.AssertionError: Attempt to repark
at java.lang.Thread.parkFor$(Thread.java:2143)
at sun.misc.Unsafe.park(Unsafe.java:325)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:161)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:840)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1220)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:312)
at com.kabouzeid.gramophone.service.ffmpeg.AudioContext.internalWrite(AudioContext.java:197)
at com.kabouzeid.gramophone.service.ffmpeg.AudioContext.write(AudioContext.java:177)
at com.kabouzeid.gramophone.service.ffmpeg.FFmpegPlayer.decodeAndPlayAudio(Native Method)
at com.kabouzeid.gramophone.service.ffmpeg.FFmpegPlayer.lambda$new$0(FFmpegPlayer.java:72)
at com.kabouzeid.gramophone.service.ffmpeg.-$$Lambda$FFmpegPlayer$MKAlsDZBJzprKYoChfgA-0JlIi8.run(lambda)
at java.lang.Thread.run(Thread.java:761)

即使没有其他线程尝试运行此代码,并且即使我注释掉所有其他尝试锁定/解锁此锁(由其他线程,在不同的代码部分中),也会发生这种情况。这个问题很少会间歇性地发生,但当我尝试取消暂停正在写入的 AudioTrack 时会可靠地发生。最初写入它或执行其他任何操作(例如从头开始播放)时都不会发生这种情况。这种取消暂停发生在一个完全不同的线程上,我无法确定这两件事之间的因果关系。这可能只是一些随机调度程序的疯狂。
internalWrite方法被非常频繁地调用,大约每秒数千次。我有一种感觉,这只是 Android 的 ReentrantLock 实现中的一个错误。 ,假设被命中的断言完全在 JVM 代码中。 (“尝试重新 parking ”是什么意思?)但我不能排除我在自己的代码中遗漏了一些其他细节,如果对此有任何想法,我将不胜感激!

完整代码可见 here .我还追踪了 Android 代码中的相关部分: AudioTrack#write , native_write_byte (方法调用不同), writeToTrack , AudioTrack->write .但是,他们根本没有帮助我阐明这个错误。

最佳答案

  • 如果您能够删除 lock.unlock()里面 track.write(data, offset, size, AudioTrack.WRITE_NON_BLOCKING);然后您的当前代码将可以正常工作,无需进行任何修改。

  • (或者)
  • 如果您无法删除 lock.unlock()里面 track.write(data, offset, size, AudioTrack.WRITE_NON_BLOCKING);当前代码需要适应 两次获取锁 :
    lock.lockInterruptibly();
    lock.lockInterruptibly();
  • public int internalWrite(byte[] data, int offset, int size) throws InterruptedException {
    lock.lockInterruptibly();
    lock.lockInterruptibly();
    try {
    if (state == State.RELEASED) throw new TrackReleasedException();
    return track.write(data, offset, size, AudioTrack.WRITE_NON_BLOCKING);
    } finally {
    if (!lock.isHeldByCurrentThread()) {
    Log.e("phonographnative", "internalWrite() lock is not held by current thread! " + Thread.currentThread());
    } else lock.unlock();
    }
    }

    关于java - ReentrantLock 在同一个线程中被神秘地解锁,即使没有其他线程正在访问它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55259970/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com