いくつかの「観察可能な」プロパティを持つクラスを定義しました。内部的に、クラスには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() ...
}
}
私の質問は、クラスのロックを保持している間、プロパティ変更イベントを発生させないようにする必要がありますか?...または、単一の専用スレッド(「event-multicaster」スレッドなど)からプロパティ変更イベントを発生させる必要がありますか?
現在の設計ではデッドロックが発生しており、スレッドAは外部クラスのロックを取得します。Bar
次に、メソッドを呼び出してFoo
2番目のロックを取得しようとします。ただし、同時に、I / OスレッドはsetState(State)
ロックオンの取得を呼び出しますFoo
。これにより、プロパティ変更イベントが含まれているクラスに伝播され、Bar
このクラスのロックを取得しようとします...デッドロックが発生します。つまり、プロパティ変更コールバックの設計は、ロックが取得される順序を効果的に制御できないことを意味します。
私の現在の回避策は、状態を作成してキーワードvolatile
を削除することsynchronized
ですが、これは厄介なようです。一つには、それはプロパティ変更イベントが発生する順序が保証されていないことを意味します。