I read that volatile variable copy will shared by all the threads and once completion of the execution, the update value will get by every thread,But in the following program using thread pool not giving the output which I expected, can any one tell me the reason?
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class Task implements Runnable{
volatile int v1=10;
private String name;
public Task(String name) {
this.name=name;
}
public synchronized void run() {
v1=v1+10;
System.out.println(name +"is entered "+v1);
}
}
public class ThreadPoolTest {
public static void main(String[] args) {
Runnable r1 = new Task("Thread 1");
Runnable r2 = new Task("Thread 2");
Runnable r3 = new Task("Thread 3");
ExecutorService executor = Executors.newFixedThreadPool(5);
executor.execute(r1);
executor.execute(r2);
executor.execute(r3);
executor.shutdown();
}
}
outPut:
Thread 1is entered 20
Thread 2is entered 20
Thread 3is entered 20
but if we change from volatile to static its giving below output:
Thread 1is entered 20
Thread 3is entered 30
Thread 2is entered 40
The observed result is correct as you are creating three separate Task
instances who are having their own copy of the name
variable.
So although they are volatile
the values are not updated by other threads the thread executing the particular instance is the one which is updating the v1
field.
If the v1
is made static then it becomes a class
member so obviously the threads will update the same copy of the variable v1
.
Instead of using synchronized
on the run
method, we can use the AtomicInteger
to safely update and fetch the value.
class Task implements Runnable{
private final AtomicInteger v1 = new AtomicInteger(10);
private String name;
public void run() {
System.out.println("Thread is: " + Thread.currentThread().getName() + " " + v1.addAndGet(10));
}
}
public class ThreadPoolTest{
public static void main(String[] args) {
Runnable r1 = new Task();
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.execute(r1);
executor.execute(r1);
executor.execute(r1);
executor.shutdown();
}
}