簡體   English   中英

Java-多線程不可變對象

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM