简体   繁体   English

Java-多线程不可变对象

[英]Java - Multithreads immutable object

I have this class: 我有这个课:

class S2Es2SharedState {
    public int x;
    public int y;
}

that is used to share an s2Es2SharedState object in every thread inside in the loop: 用于在循环内的每个线程中共享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++;  
        }
    }
}

in this program working 10 threads where each of them enter in the loop and increment 150 times the value of x and y of the shared object, so the final result in the x and y of the shared object is 1500. 在该程序中,工作10个线程,每个线程进入循环并递增共享对象的x和y的值的150倍,因此共享对象的x和y的最终结果为1500。
If i don't change anything this program have a problem of race condition, so for fix this problem i used the lock (and it works). 如果我什么都没做,这个程序就会出现竞争状况的问题,所以为了解决这个问题,我使用了锁(并且可以正常工作)。
But now i want to fix the problem of the race condition using the immutable object instead of the locks. 但是现在我想使用不可变对象而不是锁来解决竞争条件的问题。 so i changed the class of the shared object in this way: 所以我以这种方式更改了共享对象的类:

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);
    }
}

and in the run() method i changed the state variable in this way: 在run()方法中,我以这种方式更改了状态变量:

class S2Es2Worker implements Runnable {
     ....
     private volatile S2Es2SharedState state;
     ....

and in the for loop i did this edit: 在for循环中,我进行了以下编辑:

for (int i = 0; i < 150; i++) {
            state = state.incrementX();

            try {
                Thread.sleep(delay);
            } catch (final InterruptedException e) {
                // do nothing
            }

            state = state.incrementY();

        }
    }

But i don't know why the final result is that the shared object has instead of x=1500 and y=1500 但是我不知道为什么最终结果是共享对象具有x = 1500和y = 1500
150 in both variable 两个变量均为150

How can i fix the problem with the race of condition using the immutable object? 如何使用不可变对象解决条件竞赛的问题?

I'm going to assume you create a S2Es2SharedState (use simpler names for asking questions) as 我假设您创建一个S2Es2SharedState (使用更简单的名称来提问),如下所示

 S2Es2SharedState state = new S2Es2SharedState(0, 0)

and passing it to the S2Es2Worker instances something like 并将其传递给S2Es2Worker实例,例如

for (int i = 0; i < 10;i++) {
    S2Es2Worker worker = new S2Es2Worker(i, state, 5);
    new Thread(worker).start();
}

In java, everything is passed by value. 在Java中,一切都是通过值传递的。 So the using state as a method argument, a copy of the value of the reference is passed. 因此,使用state作为方法参数时,将传递引用值的副本。

So the field 所以这个领域

private volatile S2Es2SharedState state;

is also referencing the same object. 也引用相同的对象。 However, if you change the reference that the field state is holding, for example with 但是,如果更改了字段state保留的引用,例如

state = state.incrementX();

that doesn't affect any other references. 不会影响任何其他引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM