[英]Java - Multithreads immutable object
我有這個課:
class S2Es2SharedState {
public int x;
public int y;
}
用於在循環內的每個線程中共享s2Es2SharedState對象:
class S2Es2Worker implements Runnable {
private final int id;
private S2Es2SharedState state;
private final int delay;
private int numErrors = 0;
public S2Es2Worker(final int id, final S2Es2SharedState state,
final int delay) {
this.state = state;
this.delay = delay;
this.id = id;
this.numErrors = 0;
System.out.println("Worker " + id + ": created with " + delay
+ " ms delay");
}
@Override
public void run() {
boolean check = true;
System.out.println("Worker " + id + ": started");
for (int i = 0; i < 150; i++) {
state.x++;
try {
Thread.sleep(delay);
} catch (final InterruptedException e) {
// do nothing
}
state.y++;
}
}
}
在該程序中,工作10個線程,每個線程進入循環並遞增共享對象的x和y的值的150倍,因此共享對象的x和y的最終結果為1500。
如果我什么都沒做,這個程序就會出現競爭狀況的問題,所以為了解決這個問題,我使用了鎖(並且可以正常工作)。
但是現在我想使用不可變對象而不是鎖來解決競爭條件的問題。 所以我以這種方式更改了共享對象的類:
final class S2Es2SharedState {
private final int x;
private final int y;
public S2Es2SharedState(final int x, final int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public S2Es2SharedState incrementX() {
return new S2Es2SharedState(x+1, y);
}
public S2Es2SharedState incrementY() {
return new S2Es2SharedState(x, y+1);
}
}
在run()方法中,我以這種方式更改了狀態變量:
class S2Es2Worker implements Runnable {
....
private volatile S2Es2SharedState state;
....
在for循環中,我進行了以下編輯:
for (int i = 0; i < 150; i++) {
state = state.incrementX();
try {
Thread.sleep(delay);
} catch (final InterruptedException e) {
// do nothing
}
state = state.incrementY();
}
}
但是我不知道為什么最終結果是共享對象具有x = 1500和y = 1500
兩個變量均為150
如何使用不可變對象解決條件競賽的問題?
我假設您創建一個S2Es2SharedState
(使用更簡單的名稱來提問),如下所示
S2Es2SharedState state = new S2Es2SharedState(0, 0)
並將其傳遞給S2Es2Worker
實例,例如
for (int i = 0; i < 10;i++) {
S2Es2Worker worker = new S2Es2Worker(i, state, 5);
new Thread(worker).start();
}
在Java中,一切都是通過值傳遞的。 因此,使用state
作為方法參數時,將傳遞引用值的副本。
所以這個領域
private volatile S2Es2SharedState state;
也引用相同的對象。 但是,如果更改了字段state
保留的引用,例如
state = state.incrementX();
不會影響任何其他引用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.