Is the object assigned to a field defined outside the synchronized block, is it thread safe?

Is there something wrong with the thread safety of this java code? Topics 1-10 add numbers through sample.add () and Threads 11-20 call removeAndDouble () and print the results to stdout. I remember that someone said that assigning an object in the same way as mine in removeAndDouble (), using it outside the synchronized block, can be an unsafe thread. That the compiler can optimize instructions so that they come from a sequence. Is this the case here? Is the removeAndDouble () method unsafe?

Is there anything else in terms of concurrency with this code? I am trying to better understand concurrency and the memory model with java (1.6 up).

import java.util.*;
import java.util.concurrent.*;

public class Sample {

    private final List<Integer> list = new ArrayList<Integer>();

    public void add(Integer o) {
        synchronized (list) {
            list.add(o);
            list.notify();
        }
    }

    public void waitUntilEmpty() {
        synchronized (list) {
            while (!list.isEmpty()) {
                try { 
                    list.wait(10000);  
                 } catch (InterruptedException ex) { }
            }
        }
    }

    public void waitUntilNotEmpty() {
        synchronized (list) {
            while (list.isEmpty()) {
                try { 
                    list.wait(10000);  
                 } catch (InterruptedException ex) { }
            }
        }
    }

    public Integer removeAndDouble() {
        // item declared outside synchronized block
        Integer item; 
        synchronized (list) { 
            waitUntilNotEmpty();
            item = list.remove(0);
        }
        // Would this ever be anything but that from list.remove(0)?
        return Integer.valueOf(item.intValue() * 2);
    }

    public static void main(String[] args) {
        final Sample sample = new Sample();

        for (int i = 0; i < 10; i++) {
            Thread t = new Thread() {
                public void run() {
                    while (true) {
                        System.out.println(getName()+" Found: " + sample.removeAndDouble());
                    }
                }
            };
            t.setName("Consumer-"+i);
            t.setDaemon(true);
            t.start();
        }

        final ExecutorService producers = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            final int j = i * 10000;
            Thread t = new Thread() {
                public void run() {
                    for (int c = 0; c < 1000; c++) {
                        sample.add(j + c);
                    }
                }
            };
            t.setName("Producer-"+i);
            t.setDaemon(false);
            producers.execute(t);
        }

        producers.shutdown();
        try {
            producers.awaitTermination(600, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        sample.waitUntilEmpty();        
        System.out.println("Done.");
    }
}
+5
4

- .

.

-, waitUntilEmpty , list.notifyAll() list.remove(0) removeAndDouble. 10 wait(10000).

-, list.notify add(Integer) notifyAll, notify , , waitUntilEmpty waitUntilNotEmpty.

-, , , , (waitUntilEmpty), no-arg .

+6

. .

, list, . . , list item, item .

list , ( .)

+8

as-is . - .

- . , .

. , , . . . - Integer item. , .

+3

, ( ). , , .

, , java.util.concurrent BlockingQueue () . , .

+1

All Articles