我已经定义了一个具有许多“可观察”属性的类。该类在内部包含一个执行 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)
获取 lock on Foo
,这会将属性更改事件传播到包含类Bar
并尝试获取此类上的锁......导致死锁。换句话说,属性更改回调设计意味着我无法有效控制获取锁的顺序。
我目前的解决方法是创建状态volatile
并删除synchronized
关键字,但这似乎是一个杂项;一方面,这意味着无法保证触发属性更改事件的顺序。