I've defined a class with a number of "observable" properties. Internally the class contains a single thread that performs I/O; e.g.
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() ...
}
}
My question is: Should I avoid firing property change events whilst holding onto the class's lock? ... or perhaps I should be firing property change events from a single dedicated thread (e.g. "event-multicaster" thread)?
The current design is resulting in a deadlock whereby thread A takes out a lock on an external class: Bar
, and then tries to call a method on Foo
and take out a second lock. However, at the same time the I/O thread calls setState(State)
obtaining the lock on Foo
, which propagates a property changed event out to the containing class Bar
and attempts to get the lock on this class ... resulting in deadlock. In other words, the property change callback design means I cannot effectively control the order in which my locks are being obtained.
My current workaround is to make state volatile
and remove the synchronized
keywords but this seems like a kludge; for one thing it means the order in which the property change events are fired is not guaranteed.