|
|
|
/*
|
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
|
|
|
*/
|
|
|
|
|
|
|
|
import android.support.annotation.UiThread;
|
|
|
|
import android.support.annotation.WorkerThread;
|
|
|
|
|
|
|
|
class ThreadDeadlock {
|
|
|
|
Object lockA;
|
|
|
|
|
|
|
|
// methods cannot run in parallel because both are on UI thread, thus no deadlock
|
|
|
|
|
|
|
|
@UiThread
|
|
|
|
public synchronized void noParallelismAOk() {
|
|
|
|
synchronized (lockA) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@UiThread
|
|
|
|
public void noParallelismBOk() {
|
|
|
|
synchronized (lockA) {
|
|
|
|
synchronized (this) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Object lockB;
|
|
|
|
|
|
|
|
// deadlock, one method on UI thread, one on Worker thread
|
|
|
|
|
|
|
|
@UiThread
|
|
|
|
public synchronized void annotatedUiThreadBad() {
|
|
|
|
synchronized (lockB) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@WorkerThread
|
|
|
|
public void annotatedWorkerThreadBad() {
|
|
|
|
synchronized (lockB) {
|
|
|
|
synchronized (this) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Object lockC;
|
|
|
|
|
|
|
|
// deadlock as above, but here assertions are used to determine thread status
|
|
|
|
|
|
|
|
public synchronized void assertOnUIThreadBad() {
|
|
|
|
OurThreadUtils.assertOnUiThread();
|
|
|
|
synchronized (lockC) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void assertOnBackgroundThreadBad() {
|
|
|
|
OurThreadUtils.assertOnBackgroundThread();
|
|
|
|
synchronized (lockC) {
|
|
|
|
synchronized (this) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Object lockD;
|
|
|
|
|
|
|
|
// deadlock as above, though less certain because the only hint of concurrency is that
|
|
|
|
// methods take locks
|
|
|
|
|
|
|
|
public synchronized void notAnnotatedBadA() {
|
|
|
|
synchronized (lockD) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void notAnnotatedBBad() {
|
|
|
|
synchronized (lockD) {
|
|
|
|
synchronized (this) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Object lockE, lockF, lockG;
|
|
|
|
|
|
|
|
public void FP_sequentialEandGOk() {
|
|
|
|
synchronized (lockE) {
|
|
|
|
synchronized (lockF) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// at this point we still believe lockE is held
|
|
|
|
synchronized (lockG) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void FP_nestedGthenEOk() {
|
|
|
|
synchronized (lockG) {
|
|
|
|
synchronized (lockE) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|