【发布时间】:2009-09-24 11:07:40
【问题描述】:
我已经定义了一个具有许多“可观察”属性的类。该类在内部包含一个执行 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 上的方法并取出第二个锁。然而,与此同时,I/O 线程调用setState(State) 获取Foo 上的锁,这会将属性更改事件传播到包含类Bar 并尝试获取此类上的锁......结果陷入僵局。换句话说,属性改变回调的设计意味着我无法有效地控制我的锁被获取的顺序。
我目前的解决方法是设置状态 volatile 并删除 synchronized 关键字,但这似乎是一个杂项;一方面,这意味着无法保证触发属性更改事件的顺序。
【问题讨论】:
标签: java multithreading concurrency locking propertychanged