1

I have two classes

classA {
    private ArrayList<String> list = new ArrayList();

    void addString(String s){
        list.add(s);
    }

    void start(){
        new ClassB(list).start();
    }
}

classB extends Thread{
    ArrayList<String> s;
    
    public ClassB(ArrayList<String> s) { this.s = s; }
    
    void run(){
        for (String s1 : s){
        // print s1
        }
    }
}

Now when I write code as

ClassA A = new ClassA();
A.addString("1");
A.addString("2");
A.addString("3");
A.start();

I want run() in classB to print all elements in list. i.e (1, 2, 3) in this case.

Is this always default or do we need to do apply multi threading concepts to make it happen?

What if list is non-volatile? Can new thread see all the elements (1,2,3)

What if I add another element after A.start() (say A.addString("4") ), then what should I do to make new thread print all 4 elements?

1
  • If you work with a regular list from several threads you will sooner or later encounter ConcurrentModificationException. You have to use a synchronized version of your list. Even if you fix that your thread B might or might not output the value from your collection. You have to add some logic to let the thread know it has to wait for new elements and then print them once they added. Commented Sep 4, 2020 at 16:53

1 Answer 1

2

If you add all elements before starting the other thread (ClassB) it is safe. The JLS §17.4.4 says:

An action that starts a thread synchronizes-with the first action in the thread it starts.

And synchronizes-with is defined in §17.4.5.:

If an action x synchronizes-with a following action y, then we also have hb(x, y).

(hb(x, y) = x happens-before y)

So this guarantees that adding the elements happens-before reading and printing the elements.

However, with your current code, if you add elements from the main thread after you started the other thread, then you will have no thread-safety guarantees and the behavior is undefined. The other thread might see the added elements, but it could also not see them or possibly even throw an exception because it sees the data of the ArrayList in an inconsistent state.


What if I add another element after A.start() (say A.addString("4") ), then what should I do to make new thread print all 4 elements?

This is difficult to answer with your example code because it is not clear how the code should behave:

  • Should the other thread (ClassB) wait indefinitely for new elements? Then one solution could be using a BlockingQueue or using some sort of signaling and using a thread-safe collection (or synchronizing access to the ArrayList) is required.
  • Is the other thread (ClassB) allowed to miss the new elements in case it has finished printing the old elements before the new ones are added? Then only using a thread-safe collection (or synchronizing access to the ArrayList) is necessary.
  • ...
Sign up to request clarification or add additional context in comments.

2 Comments

since it is safe to add all elements before Thread.start(), do they get reflected in code present in thread. What if the list is non-volatile ? Then there is chance that new thread can't able to see all elements of list right?
"do they get reflected in code present in thread", what do you mean by that? All elements are guaranteed to be seen by the other thread if they were added before starting the thread (and if you do not add elements afterwards). "What if the list is non-volatile?"; it does not matter whether the field is volatile or not if you add all elements before starting the other thread. On the other hand volatile only makes guarantees about reading and assigning values to the field. This means just using volatile does not make it safe to add list elements after the other thread has been started.

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.