[concurrency-interest] Concurrent sequential access to a mutable field without the volatile modifier

Sébastien Bocq sebastien.bocq at gmail.com
Fri Jan 7 10:01:34 EST 2011


Hello,

I made a simple test (see below) to verify my assumption that a variable
mutated sequentially by multiple threads must be marked as volatile to have
mutations visible across these threads. How comes my test succeeds even
though I omitted the volatile keyword?

Thanks,
Sébastien

import java.util.concurrent.*;

public class VolatileTest {

    static class CountTask implements Runnable {
        public int count = 0;             // volatile omitted
        public void run() { count++; }
        @Override
        public String toString() {return String.valueOf(count);}
    };

    static class SimpleExecutor implements Runnable {

       LinkedBlockingQueue<Runnable> queue = new
LinkedBlockingQueue<Runnable>();

       public void submit(Runnable runnable) { queue.offer(runnable); }

       volatile Thread thread = null;

       public void run() {

          thread = Thread.currentThread();

          while (thread != null) {

            try {
                Runnable task = queue.take();
                task.run();
            } catch (InterruptedException e) {}
          }
       }

       public void shutdown() {
         Thread t = thread;
         thread = null;
         t.interrupt();
       }

       public SimpleExecutor() {
           new Thread(this).start();
       }
    }

    static class LoopTask implements Runnable {
        CountDownLatch latch;
        int count;
        Runnable task;
        SimpleExecutor[] executors;

        /** Repeat a task sequentially using different executors
         *
         * @param executors the executors
         * @param count     the number of iterations
         * @param latch     latch decremented after the last iteration
         * @param task      the task invoked repeatedly
         */
        public LoopTask(SimpleExecutor[] executors, int count,
CountDownLatch latch, Runnable task) {
            this.executors = executors;
            this.latch = latch;
            this.count = count;
            this.task  = task;
        }

        public void run() {
            if (count == 0)
                latch.countDown();
            else {
                task.run();
                executors[count % executors.length].submit(new
LoopTask(executors, count - 1, latch, task));
            }
        }
    }

     public static void main(String[] args) throws Exception {
       int loops = 1000000;
       int nbExecs = 10;

       CountDownLatch latch = new CountDownLatch(1);
       SimpleExecutor[] executors = new SimpleExecutor[nbExecs];

       for (int i = 0; i < executors.length; i++)
         executors[i] = new SimpleExecutor();

       CountTask task = new CountTask();

       try {
           new LoopTask(executors, loops, latch, task).run();

           latch.await();

           System.out.println(task);
           assert(task.count == loops);
       } finally {
           for (int i = 0; i < executors.length; i++)
               executors[i].shutdown();
       }
     }
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20110107/d8b58217/attachment.html>


More information about the Concurrency-interest mailing list