我正在尝试确定以下java方法是否是线程安全的:
public Object calledByMultipleThreads() {
final Object[] item = new Object[1];
if (!EventQueue.isDispatchThread()) {
try {
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
helperMethod(item)
}
});
} catch (InterruptedException | InvocationTargetException ex) {
// logging...
}
} else {
helperMethod(item)
}
return item[0];
}
private void helperMethod(Object[] item) {
item[0] = new Object();
}
我知道final Object[] item = new Object[1]
是一种解决方法(因为final Object item
内部Runnable
之类的内容无法修改。由于使用invokeAndWait
,item[0]
在被return
引用之前设置,但我担心调用者线程(不是EDT)可能看不到对{的更新{1}}数组,并返回item
。这可能吗?有什么方法可以测试它的安全性吗?
答案 0 :(得分:1)
由于invokeAndWait
的实施方式的详细信息,Runnable
内发生的所有操作都发生在控制权返回invokeAndWait
的来电之前:
1233 synchronized (lock) {
1234 Toolkit.getEventQueue().postEvent(event);
1235 while (!event.isDispatched()) {
1236 lock.wait();
1237 }
1238 }
换句话说,你所做的是安全的。另一方面,通过测试无法确保这样的保证:)
答案 1 :(得分:1)
阵列不是自动线程安全的,而不是非final
实例字段。
但是,这里没有线程安全问题。在EventQueueinvokeAndWait
内的分配和返回的方法之间会有发生在之前。
注意invokeAndWait
可能导致(有效)死锁。最好使用EventQueue.invokeLater
和类似方法回发到非EDT主题。