gpt4 book ai didi

Java 同步列表死锁

转载 作者:行者123 更新时间:2023-12-03 12:57:40 25 4
gpt4 key购买 nike

来自 Effective Java 2nd edition item 67 page 266-268:

The background thread calls s.removeObserver, which attempts to lock observers, but it can’t acquire the lock, because the main thread already has the lock. All the while, the main thread is waiting for the background thread to finish removing the observer, which explains the deadlock.



我试图通过使用 ThreadMXBean ( Programmatic deadlock detection in java ) 在 main 方法中找出哪些线程死锁,但为什么它不返回死锁线程?
我使用了一个新线程来运行 ThreadMXBean 检测。
public class ObservableSet<E> extends ForwardingSet<E> { 
public ObservableSet(Set<E> set) { super(set); }
private final List<SetObserver<E>> observers =
new ArrayList<SetObserver<E>>();
public void addObserver(SetObserver<E> observer) {
synchronized(observers) {
observers.add(observer);
}
}
public boolean removeObserver(SetObserver<E> observer) {
synchronized(observers) {
return observers.remove(observer);
}
}
private void notifyElementAdded(E element) {
synchronized(observers) {
for (SetObserver<E> observer : observers)
observer.added(this, element);
}
}
@Override
public boolean add(E element) {
boolean added = super.add(element); if (added)
notifyElementAdded(element); return added;
}
@Override
public boolean addAll(Collection<? extends E> c) {
boolean result = false; for (E element : c)
result|=add(element); //callsnotifyElementAdded
return result;
}

public static void main(String[] args) {
ObservableSet<Integer> set =
new ObservableSet<Integer>(new HashSet<Integer>());

final ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();

Thread t = new Thread(new Runnable() {
@Override
public void run() {
while( true ) {
long [] threadIds = threadMxBean.findDeadlockedThreads();
if( threadIds != null) {
ThreadInfo[] infos = threadMxBean.getThreadInfo(threadIds);
for( ThreadInfo threadInfo : infos) {
StackTraceElement[] stacks = threadInfo.getStackTrace();
for( StackTraceElement stack : stacks ) {
System.out.println(stack.toString());
}
}
}
try {
System.out.println("Sleeping..");
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
t.start();


set.addObserver(new SetObserver<Integer>() {
public void added(ObservableSet<Integer> s, Integer e) {
ExecutorService executor = Executors.newSingleThreadExecutor();
final SetObserver<Integer> observer = this; try {
executor.submit(new Runnable() {
public void run() {
s.removeObserver(observer);
} }).get();
} catch (ExecutionException ex) {
throw new AssertionError(ex.getCause());
} catch (InterruptedException ex) {
throw new AssertionError(ex.getCause());
} finally {
executor.shutdown();
}
}
});

for (int i = 0; i < 100; i++)
set.add(i);
}
}

public interface SetObserver<E> {
// Invoked when an element is added to the observable set
void added(ObservableSet<E> set, E element);
}


// ForwardingSet<E> simply wraps another Set and forwards all operations to it.

最佳答案

你有一个僵局。

但是,您没有循环,这就是 ThreadMXBean#findDeadlockedThreads 方法声明它搜索的内容。从javadoc:

Finds cycles of threads that are in deadlock waiting to acquire object monitors or ownable synchronizers. Threads are deadlocked in a cycle waiting for a lock of these two types if each thread owns one lock while trying to acquire another lock already held by another thread in the cycle.



在这种情况下,主线程正在等待 Future 的结果。而另一个线程(不持有锁)正在等待主线程释放其锁。

关于Java 同步列表死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2609036/

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