我一直在閱讀關於同步和易變關鍵字/ idoms的不少文章,我想我正確理解它們是如何工作的以及它們應該在何時使用。不過,我仍然對我正在嘗試做的事情有些懷疑。考慮以下內容:併發訪問:波動性和同步
public class X {
private volatile int x;
public X(int x) {
this.x = x;
}
public void setX(int x) {
this.x = x;
}
public int getX() {
return x;
}
}
上面的代碼非常直接,也是線程安全的。現在考慮同一類X有以下變化:
public class X {
private volatile int x;
private volatile Y yObj;
private volatile boolean active;
public X(Y yObj) {
this.yObj = yObj;
active = false;
x = yObj.getY();
}
public void setX(int x) {
if (active) throw new IllegalStateException()
if (!yObj.isValid(x)) throw new IllegalArgumentException();
this.x = x;
}
public void setY(Y yObj) {
if (active) throw new IllegalStateException();
this.yObj = yObj;
x = yObj.getY();
}
public int getX() {
return x;
}
public Y getY() {
return yObj;
}
public synchronized void start() {
if (active) throw new IllegalStateException();
/*
* code that performs some initializations and condition checking runs here
* does not depend on x and yObj
* might throw an exception
*/
active = true;
}
public synchronized void stop() {
if (!active) throw new IllegalStateException();
/* some code in the same conditions of the comments in the start()
* method runs here
*/
active = false;
}
public boolean isActive() {
return active;
}
}
現在,我宣佈yObj
爲volatile
,以確保每一個線程看到同一個對象引用時通過調用setY(Y)
方法改變。 Y
類的想法是在調用X
對象的setter時爲X
類提供一組參數值(在本例中僅爲一個參考值)。這些問題是:
- 可以
x
仍然被宣佈爲volatile
,並確保所有線程共同的可見性或需要進一步的同步? - 這個想法是使類
Y
的所有對象不可變。所以,我認爲它的所有字段也必須是不可變的。使用Y
用戶可以實現的最好方式是什麼,但同時又是線程安全的?一個實現線程安全機制的抽象類,然後它可以被擴展?目前,Y
是一個可以實現的getter方法的接口,當然不是線程安全的。 - 啓動/停止機制是否從併發訪問的角度正確實現?
'setY'例如使用2個不同步的操作。 'getX()'可能不會看到新的'x',而是新的'yObj'。這可能不是線程安全的。 'setX'和'setY'也不安全,你可以用setX中的x來結束,但是setY – zapl
@zapl中的y你是對的,錯過了。感謝您指出了這一點! – acostalima