我定义了一个具有多个“可观察”属性的类。在内部,该类包含执行I/O操作的单个线程;例如:
public class Foo {
private final PropertyChangeSupport support;
private State state;
public Foo() { this.support = new PropertyChangeSupport(this); }
public synchronized State getState() { return state; }
public synchronized void setState(State state) {
if (this.state != state) {
State oldState = this.state;
this.state = state;
// Fire property change *whilst still holding the lock*.
support.firePropertyChange("state", oldState, state);
}
}
public synchronized void start() {
// Start I/O Thread, which will call setState(State) in some circumstances.
new Thread(new Runnable() ...
}
}
我的问题是:在持有类的锁时,我应该避免触发属性更改事件吗?或者也许我应该从单个专用线程(例如“事件多路广播器”线程)触发属性更改事件?
当前的设计导致了死锁,其中线程A获取了外部类
Bar
的锁,然后尝试调用Foo
上的方法并取出第二个锁。但与此同时,I/O线程调用setState(State)
来获取Foo
上的锁,这会将属性更改事件传播到包含类Bar
并尝试获取此类的锁... 从而导致死锁。换句话说,属性更改回调设计意味着我无法有效地控制获取锁的顺序。我的当前解决方法是使状态
volatile
并删除synchronized
关键字,但这似乎不太好;首先,这意味着不能保证触发属性更改事件的顺序。