1

我正在尝试确定以下 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)可能看不到对item数组的更新,并返回null。这可能吗?有什么方法可以测试它的安全性吗?

4

2 回答 2

1

由于如何invokeAndWait实现的细节,所有在Runnable 发生之前发生的动作都将控制权返回给调用者invokeAndWait

1233  同步(锁定){ 
1234 工具包。获取事件队列()。postEvent(事件);
1235 while (! event.isDispatched ()) {
1236 锁。等待();
1237 }
1238 }

换句话说,你正在做的事情是安全的。另一方面,没有办法通过测试来确保这样的保证:)

于 2013-02-20T18:20:31.397 回答
1

final与非实例字段相比,数组不会自动成为线程安全的。

但是,这里不存在线程安全问题。在内部分配和该方法返回之间会有一个happens-before 。EventQueueinvokeAndWait

注意invokeAndWait容易导致(有效的)死锁。EventQueue.invokeLater使用类似的方法回发到非 EDT 线程要好得多。

于 2013-02-20T18:20:34.860 回答