У меня есть некоторый код, который, я думаю, будет очень простым:
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();
}
}
lock
- это fair
ReentrantLock, но проблема также возникает с не-1006 *.track
- Android AudioTrack;его write
метод в основном нативный код (но не имеет ничего общего с многопоточностью).В любом случае у него нет доступа к 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.(Что означает «Попытка перепарковки»?) Но я не могу исключить, что пропустил некоторые другие детали в своем собственном коде, и я был бы признателен за любые мысли по этому поводу!
Полный код можетможно найти здесь .Я также отследил соответствующие разделы в коде Android: AudioTrack # write , native_write_byte (метод вызывается по-другому), writeToTrack , AudioTrack-> запись .Однако они никак не помогли мне выяснить эту ошибку.