My understanding is that Java allows threads to access shared variables. As a rule, to ensure that shared variables are consistently updated, a thread should ensure that it has exclusive use of such variables by obtaining a lock that enforces mutual exclusion for those shared variables.If a field is declared volatile, in that case the Java memory model ensures that all threads see a consistent value for the variable.
In case of program below , tickectsAvailable is a shared variable which is stored on heap and because thread1 and thread2, are created on same object "obj" , both thread1 and thread2 have access to obj
I am trying to understanding when to make a variable volatile. Correct use case would be here in this case making "tickectsAvailable" volatile. Is my understanding on volatile variables correct?
I read an article that says : Each thread may copy variables from main memory into a CPU cache while working on them, for performance reasons. If your computer contains more than one CPU, each thread may run on a different CPU. That means, that each thread may copy the variables into the CPU cache of different CPUs
In this case, if i do not make "tickectsAvailable" volatile, there are changes that threads may read from CPU cache if i have multiple threads working of same object("obj") here in case of only more than one CPU?
Should Volatile variable be used only when your computer contains multiple CPU's? But if i have multiple threads on same obj and one cpu how is it going to behave?
class TicketBooking implements Runnable{
int ticketsAvailable=1;
public void run(){
System.out.println("Waiting to book ticket for : "+Thread.currentThread().getName());
synchronized (this) {
if(ticketsAvailable>0){
System.out.println("Booking ticket for : "+Thread.currentThread().getName());
//Let's say system takes some time in booking ticket (here we have taken 1 second time)
try{
Thread.sleep(1000);
}catch(Exception e){}
ticketsAvailable--;
System.out.println("Ticket BOOKED for : "+ Thread.currentThread().getName());
System.out.println("currently ticketsAvailable = "+ticketsAvailable);
}
else{
System.out.println("Ticket NOT BOOKED for : "+
Thread.currentThread().getName());
}
}//End synchronization block
}
}
/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
public class MyClass {
public static void main(String args[])
{
TicketBooking obj=new TicketBooking();
Thread thread1=new Thread(obj,"Passenger1 Thread");
Thread thread2=new Thread(obj,"Passenger2 Thread");
thread1.start();
thread2.start();
}
}
/*OUTPUT
Waiting to book ticket for : Passenger2 Thread
Waiting to book ticket for : Passenger1 Thread
Booking ticket for : Passenger2 Thread
Ticket BOOKED for : Passenger2 Thread
currently ticketsAvailable = 0
Ticket NOT BOOKED for : Passenger1 Thread
*/