0

After the following code

ArrayList<String> foo, bar, test;
foo = new ArrayList<String>(Arrays.asList("foo")); 
bar = new ArrayList<String>(Arrays.asList("bar"));
test = new ArrayList<String>(Arrays.asList("test"));

Thread 1 runs:

foo = new ArrayList<String>(bar);

Thread 2 runs:

bar = new ArrayList<String>(test);

Can this cause an exception if Thread 2 changes value of bar while it is being used by Thread 1?

3
  • This is concurrent access to a reference, not the list itself. Commented Mar 30, 2017 at 11:49
  • No excpetions will be thrown for this, but if this is a concern for you you have probably created a race condition. Commented Mar 30, 2017 at 11:52
  • 2
    "changes value of bar" - bar will not be affected if the reference is changed; the other threads will still have a reference to the original list. So "no". Commented Mar 30, 2017 at 11:52

2 Answers 2

1

You won't get a concurrent modification exception, since the list instances are never mutated. Only references are exchanged.

However you still have a data race:

  • Either the assignment in Thread1 runs first. Thread1 will capture the initial bar object and create a new `foo´ which is the copy of that.
  • Or the assignment in Thread2 will run first, which means it creates a new list which is stored in the bar reference, and when Thread1 runs later on it will end up with a copy of that one, which itself is a copy of the test list.
Sign up to request clarification or add additional context in comments.

Comments

0

It is not a problem at all. To understand what happens you need to know how java handles such structures as ArrayList (and other collections).

When you create a new ArrayList variable, the variable contains only the link to the segment of RAM where the real data is kept. When you pass the variable to a constructor or another method, java copies the value of the variable, and the parameter is initialized with this value. So when you assign a new list to the parameter, you don't change the value of the original variable:

public class Main {

    public static void main(String [] args) throws IOException {
        List<String> foo, bar, test;
        foo = new ArrayList<String>(Arrays.asList("foo")); 
        bar = new ArrayList<String>(Arrays.asList("bar"));
        test = new ArrayList<String>(Arrays.asList("test"));

        CountDownLatch cdl = new CountDownLatch(1);

        Thread r1 = new Thread(new MyThread("foo = new ArrayList(bar)", bar, foo, cdl));
        Thread r2 = new Thread(new MyThread("bar = new ArrayList(test)", test, bar, cdl)); 
        r1.start();
        r2.start();

        cdl.countDown();
        System.out.println("Size of foo is " + foo.size());
        System.out.println("Size of bar is " + foo.size());
    }
}

class MyThread implements Runnable {

    private List<String> src;
    private List<String> dst;
    private CountDownLatch cdl;
    private String msg;

    public MyThread(String msg, List<String> src, List<String> dst, CountDownLatch cdl) {
        this.msg = msg;
        this.src = src;
        this.dst = dst;
        this.cdl = cdl;
    }

    @Override
    public void run() {
        try {
            cdl.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        dst = new ArrayList<String>(src);
        dst.add("test");
        System.out.println(msg + " and my size is " + dst.size());
    }

}

Output:

bar = new ArrayList(test) and my size is 2
foo = new ArrayList(bar) and my size is 2
Size of foo is 1
Size of bar is 1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.