将同步方法转换为非阻塞算法
Convert synchronized methods to non-blocking algorithm
刚找到一些关于非阻塞算法的资料,所以想在实践中使用它们。我将一些代码从同步更改为非阻塞,所以我想问一下我是否做对了一切并保存了以前的功能。
同步代码:
protected PersistentState persistentState;
protected ClassConstructor(final ID id)
{
super(id);
this.persistentState = PersistentState.UNKNOWN;
}
public final synchronized PersistentState getPersistentState()
{
return this.persistentState;
}
protected synchronized void setPersistentState(final PersistentState newPersistentState)
{
if (this.persistentState != newPersistentState)
{
this.persistentState = newPersistentState;
notifyPersistentStateChanged();
}
}
我在非阻塞算法中的替代方案:
protected AtomicReference<PersistentState> persistentState;
protected ClassConstructor(final ID id)
{
super(id);
this.persistentState = new AtomicReference<PersistentState>(PersistentState.UNKNOWN);
}
public final PersistentState getPersistentState()
{
return this.persistentState.get();
}
protected void setPersistentState(final PersistentState newPersistentState)
{
PersistentState tmpPersistentState;
do
{
tmpPersistentState = this.persistentState.get();
}
while (!this.persistentState.compareAndSet(tmpPersistentState, newPersistentState));
// this.persistentState.set(newPersistentState); removed as not necessary
notifyPersistentStateChanged();
}
我是否做对了所有事情,还是遗漏了什么?对代码和使用非阻塞方法一般设置 abject 有什么建议吗?
取决于您所说的 thread-safe
是什么意思。如果两个线程尝试同时写入,您希望发生什么情况?是否应该随机选择其中之一作为正确的新值?
这是最简单的。
protected AtomicReference<PersistentState> persistentState = new AtomicReference<PersistentState>(PersistentState.UNKNOWN);
public final PersistentState getPersistentState() {
return this.persistentState.get();
}
protected void setPersistentState(final PersistentState newPersistentState) {
persistentState.set(newPersistentState);
notifyPersistentStateChanged();
}
private void notifyPersistentStateChanged() {
}
这仍然会在所有情况下调用 notifyPersistentStateChanged
,即使状态没有改变。您需要决定在那种情况下应该发生什么(一个线程使 A -> B 而另一个线程使 B -> A)。
但是,如果您只需要在成功转换值后调用 notify
,您可以尝试这样的操作:
protected void setPersistentState(final PersistentState newPersistentState) {
boolean changed = false;
for (PersistentState oldState = getPersistentState();
// Keep going if different
changed = !oldState.equals(newPersistentState)
// Transition old -> new successful?
&& !persistentState.compareAndSet(oldState, newPersistentState);
// What is it now!
oldState = getPersistentState()) {
// Didn't transition - go around again.
}
if (changed) {
// Notify the change.
notifyPersistentStateChanged();
}
}
刚找到一些关于非阻塞算法的资料,所以想在实践中使用它们。我将一些代码从同步更改为非阻塞,所以我想问一下我是否做对了一切并保存了以前的功能。
同步代码:
protected PersistentState persistentState;
protected ClassConstructor(final ID id)
{
super(id);
this.persistentState = PersistentState.UNKNOWN;
}
public final synchronized PersistentState getPersistentState()
{
return this.persistentState;
}
protected synchronized void setPersistentState(final PersistentState newPersistentState)
{
if (this.persistentState != newPersistentState)
{
this.persistentState = newPersistentState;
notifyPersistentStateChanged();
}
}
我在非阻塞算法中的替代方案:
protected AtomicReference<PersistentState> persistentState;
protected ClassConstructor(final ID id)
{
super(id);
this.persistentState = new AtomicReference<PersistentState>(PersistentState.UNKNOWN);
}
public final PersistentState getPersistentState()
{
return this.persistentState.get();
}
protected void setPersistentState(final PersistentState newPersistentState)
{
PersistentState tmpPersistentState;
do
{
tmpPersistentState = this.persistentState.get();
}
while (!this.persistentState.compareAndSet(tmpPersistentState, newPersistentState));
// this.persistentState.set(newPersistentState); removed as not necessary
notifyPersistentStateChanged();
}
我是否做对了所有事情,还是遗漏了什么?对代码和使用非阻塞方法一般设置 abject 有什么建议吗?
取决于您所说的 thread-safe
是什么意思。如果两个线程尝试同时写入,您希望发生什么情况?是否应该随机选择其中之一作为正确的新值?
这是最简单的。
protected AtomicReference<PersistentState> persistentState = new AtomicReference<PersistentState>(PersistentState.UNKNOWN);
public final PersistentState getPersistentState() {
return this.persistentState.get();
}
protected void setPersistentState(final PersistentState newPersistentState) {
persistentState.set(newPersistentState);
notifyPersistentStateChanged();
}
private void notifyPersistentStateChanged() {
}
这仍然会在所有情况下调用 notifyPersistentStateChanged
,即使状态没有改变。您需要决定在那种情况下应该发生什么(一个线程使 A -> B 而另一个线程使 B -> A)。
但是,如果您只需要在成功转换值后调用 notify
,您可以尝试这样的操作:
protected void setPersistentState(final PersistentState newPersistentState) {
boolean changed = false;
for (PersistentState oldState = getPersistentState();
// Keep going if different
changed = !oldState.equals(newPersistentState)
// Transition old -> new successful?
&& !persistentState.compareAndSet(oldState, newPersistentState);
// What is it now!
oldState = getPersistentState()) {
// Didn't transition - go around again.
}
if (changed) {
// Notify the change.
notifyPersistentStateChanged();
}
}