JAVA concurrent programming 4 _ volatile keyword for Thread Synchronization

Source: Internet
Author: User

JAVA concurrent programming 4 _ volatile keyword for Thread Synchronization

 

In the previous blog, the synchronized keyword of JAVA concurrent programming 3 _ thread synchronization explains the key word synchronized in JAVA to ensure thread synchronization. In fact, there is a weak synchronization mechanism volatile in JAVA. The volatile keyword is a lightweight synchronization mechanism in JAVA used to synchronize variable update operations to other threads. From the perspective of memory visibility, writing the volatile variable is equivalent to exiting the synchronization code block, and reading the volatile variable is equivalent to entering the synchronization code block.

Old memory Model: ensure that read/write volatile occurs directly in main memory.

In the new memory model (1.5), the volatile semantics is fixed and enhanced: If thread A writes volatile variable V and thread B reads V, when writing V, all variable values visible to A can now be visible to B.

In a word, volatile ensures visibility, but cannot guarantee atomicity.

Atomicity: A group of statements are executed as an inseparable unit. It is impossible for any thread that executes the synchronization code block to see that other threads are executing the synchronization code block protected by the same lock. The non-atomicity of volatile variables is the easiest to ignore.

Visibility: A thread modifies the value of a shared variable. Other threads can immediately learn the modification.

Non-atomicity of volatile

Variables defined as volatile cannot guarantee that all operations on them are atomic. Due to non-atomicity, volatile cannot guarantee the security of concurrent threads. The following code:

Public class Test implements Runnable {public volatile int race = 0; @ Overridepublic void run () {increase ();} private void increase () {race ++ ;} public static void main (String [] args) {Test t = new Test (); Thread [] threads = new Thread [1000]; for (int I = 0; I <1000; I ++) {threads [I] = new Thread (t); threads [I]. start () ;}while (Thread. activeCount ()> 1) {Thread. yield () ;}// ensure that all the 1000 threads have been executed during printing. System. out. println (t. race );}}

This Code enables 1000 threads to perform auto-increment operations on the race variable. Theoretically, if the thread is secure, the execution result should be 1000. But in fact, the result of execution is a value smaller than 1000.

After analyzing the code in the above case, the problem lies in the race ++ code. It is not an atomic operation. This code is actually divided into three operations: Reading the value of race, adding 1, and writing new values.

Obviously, defining variables as vilatile does not guarantee atomicity:

Thread 1 first reads the original value of the variable race, and thread 1 is blocked; thread 2 also reads the original value of the variable race, and then adds 1, and write the value after + 1 into the working memory, and finally write the value to the main memory. Then thread 1 is followed by the addition of 1. As the value of race has been read, in this case, the race value in the worker memory of thread 1 is still the previous value. Therefore, after thread 1 adds 1 to the race, the value is the same as the previous one, write the value to the working memory and write it to the primary memory. In this way, two threads are added only once after auto-increment. The reason is that volatile cannot guarantee atomicity.

You can change the auto-increment operation to a synchronous code block.

private synchronized void increase() {race ++;}
Volatile visibility

A thread modifies the value of a volatile variable, which is immediately visible to other threads.

 

boolean ready;// thread 1while (!ready) {       doSomthing();}// thread2ready = true;

 

This is a common method for thread destruction. However, the problem is that the ready variable is changed to true before it can be written to the primary memory, and then it is transferred to other threads for execution, and then it enters a loop. At this time, the role of volatile is shown. The volatile variable ensures that it is immediately known to other threads after being modified in one thread.

Use Cases of volatile variables this article is very detailed: Java Theory and Practice: Correct Use of Volatile Variables

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.