I believe that readers who understand Java multi-threading will know its role clearly. The volatile keyword is used to declare simple type variables, such as int, float, boolean and other data types. If these simple data types are declared volatile, operations on them become atomic. But this has certain limitations. For example, n in the following example is not atomic:
Copy the code code as follows:
package mythread;
public class JoinThread extends Thread
{
public static volatile int n = 0;
public void run()
{
for (int i = 0; i < 10; i++)
try
{
n = n + 1;
sleep(3); // In order to make the running results more random, delay 3 milliseconds
}
catch (Exception e)
{
}
}
public static void main(String[] args) throws Exception
{
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
// Create 100 threads
threads[i] = new JoinThread();
for (int i = 0; i < threads.length; i++)
//Run the 100 threads just created
threads[i].start();
for (int i = 0; i < threads.length; i++)
//Continue after all 100 threads have been executed
threads[i].join();
System.out.println("n=" + JoinThread.n);
}
}
If the operation on n is atomic, the final output result should be n=1000. However, when executing the above area code, the output n is often less than 1000, which shows that n=n+1 is not an atomic level operation. . The reason is that for a simple variable declared volatile, if the current value is related to the previous value of the variable, then the volatile keyword has no effect, which means that the following expressions are not atomic operations:
Copy the code code as follows:
n = n + 1;
n++;
If you want to make this situation an atomic operation, you need to use the synchronized keyword. The above code can be changed to the following form:
Copy the code code as follows:
package mythread;
public class JoinThread extends Thread
{
public static int n = 0;
public static synchronized void inc()
{
n++;
}
public void run()
{
for (int i = 0; i < 10; i++)
try
{
inc(); // n = n + 1 changed to inc();
sleep(3); // In order to make the running results more random, delay 3 milliseconds
}
catch (Exception e)
{
}
}
public static void main(String[] args) throws Exception
{
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
// Create 100 threads
threads[i] = new JoinThread();
for (int i = 0; i < threads.length; i++)
//Run the 100 threads just created
threads[i].start();
for (int i = 0; i < threads.length; i++)
//Continue after all 100 threads have been executed
threads[i].join();
System.out.println("n=" + JoinThread.n);
}
}
The above code changes n=n+1 to inc(), where the inc method uses the synchronized keyword for method synchronization. Therefore, be careful when using the volatile keyword. It does not mean that simple type variables are modified with volatile. All operations on this variable are the original operations. When the value of the variable is determined by its previous one, such as n=n+1 , n++, etc., the volatile keyword will be invalid. The operation on the variable is atomic level only when the value of the variable has nothing to do with its previous value. For example, n = m + 1, this is the original level. Therefore, you must be cautious when using volatile keys. If you are not sure, you can use synchronized instead of volatile.