Analysis of volatile and synchronized usage in Java multithreading

  • 2020-04-01 03:38:28
  • OfStack

This article provides an example of the use of volatile and synchronized in Java multithreading. Share with you for your reference. The specific implementation method is as follows:

package com.chzhao;
public class Volatiletest extends Thread {
    private static int count = 0;
    public void run() {
        count++;
    }     public static void main(String[] args) {
        Thread threads[] = new Thread[10000];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Volatiletest();
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(count);
    }
}

The code above expects the output to be 10,000, and since count++ is not thread-safe, the output is often less than 10,000.

To solve this problem, the volatile keyword was added.

package com.chzhao;
public class Volatiletest extends Thread {
    private volatile static int count = 0;
    public void run() {
        count++;
    }     public static void main(String[] args) {
        Thread threads[] = new Thread[10000];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Volatiletest();
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(count);
    }
}

After modification, the output value is often not 10000.

Modified to the synchronized form, the code is as follows:

package com.chzhao;
public class SynchronizedTest extends Thread {
    private static int count = 0;     public void run() {
        synchronized (LockClass.lock) {
            count++;
        }
    }     public static void main(String[] args) {
        Thread threads[] = new Thread[10000];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new SynchronizedTest();
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(count);
    }
}

package com.chzhao;
public class LockClass {
    public static byte[] lock = new byte[0]; }

After this modification, the output is 10000.

Does this mean that the keyword volatile is completely useless? Only synchronized can guarantee thread safety?

Description:

The Java language includes two built-in synchronization mechanisms: synchronized blocks (or methods) and volatile variables. Both of these mechanisms are proposed to realize the security of code threads. Volatile variables are less synchronous (but sometimes simpler and less expensive) and more error-prone to use. Volatile variables in the Java language can be thought of as a "mild form of synchronized"; Volatile variables require less coding and run time overhead than synchronized blocks, but they do only a fraction of the work of synchronized.

That is, in some cases, volitile is more convenient to use than synchronized, and, of course, less synchronized.

I hope this article has been helpful to your Java programming.


Related articles: