Java multi-threaded shared variable control

Source: Internet
Author: User
Tags finally block visibility

1. Visibility

If a thread changes the value of a shared variable, it can be seen by other threads in a timely manner, known as the visibility of shared variables. If a variable has a copy in the working memory of multiple threads at the same time, then this variable is called a shared variable

2. JMM (Java memory model)

When multiple threads read and modify a shared variable of main memory at the same time, the variable is first read to its own worker thread into a copy, and then updated back to the main thread for variable memory.

Article two stipulates:

A. All operations of a thread on a shared variable must be made in working memory and cannot be directly manipulated by the main memory

B. Variables in the working memory of each other cannot be accessed between different threads, and the transfer of variable values between threads must go through main memory

If a thread 1 modification to a shared variable x is visible to thread 2, the following steps are required:

A. Thread 1 updates the value after changing X to main memory

B. Main memory updates the updated X's value to a copy of x in working memory of thread 2

Therefore, the following two points must be guaranteed to achieve the visibility of shared variables:

A. Thread changes to the working in-memory copy can be updated to main memory in a timely manner

B. Other threads can flush updates of shared variables on main memory to a copy of the variable in their working memory in a timely manner

The visibility of shared variables can be implemented in Java through synchronized, volatile, Java concurrent classes

3. Synchronized realization of visibility

Synchronized is actually a mutex that accesses the code block that modifies the shared variable, and when multiple threads access the synchronized code block, only one thread accesses and modifies the contents of the code block (locking) at some point. All other threads waiting for the thread to leave the code block (releasing the lock) have a chance to enter the synchronized code block.

So a thread enters the synchronized code block before and after it executes in the following steps:

A. Thread obtains a mutex lock

B. Empty working memory

C. Share the latest value of the variable from the main memory copy to the working memory as a copy

D. Code execution

E. Refreshing the value of a modified copy back into main memory

F. Thread-Release lock

Later, when the other code enters the synchronized code block, the value of the shared variable on the working memory read is the most recent value since the last thread was modified.

A common block of code is executed between multiple threads (access modifies shared variables), and the final value of the final shared variable may have multiple results due to thread cross execution:

PublicClasssynchronizedtest {PrivateBoolean ready =False;Privateint result = 0;Privateint number = 1;PublicvoidWrite () {ready =True; Number = 2; }PublicvoidRead () {If(Ready) {result = number * 3; } System.out.println ("result is" +result); }PrivateClass TestthreadExtendsthread{PrivateBooleanFlagPublic Testthread (BooleanFlag) {This.flag =Flag } @OverridePublicvoid run () {// TODO auto-generated Method stub ifelse{read ();}}} public static void< Span style= "color: #000000;" > main (string[] args) {synchronizedtest test = new Synchronizedtest (); Test. new testthread (truenew testthread (false) . Start (); }} 

As in the code, the result may be 0 or 6 or 3 because two threads cross execution.

Shared variables are not visible primarily for the following reasons:

A. Cross-execution of threads

B. Re-ordering

C. Shared variables not updated in a timely manner

By using synchronized, you can guarantee atomicity (synchronized code block content is either not executed, execution is guaranteed to complete) and visibility, and the modified code adds synchronized keywords to the write and read methods

4. Volatile for visibility (after JDK 1.5)

How does volatile achieve visibility?

Each time a volatile variable is accessed by a thread, it forces the thread to reread the current value of the variable from main memory, forcing the thread to flush the latest value back into main memory when the variable changes. In this way, different threads can see the latest value of the variable in a timely manner.

However, volatile does not guarantee the atomicity of variable changes:

For example number++, this operation is actually a collection of three operations (read Number,number plus 1, write the new value back to number), volatile can only guarantee that the operation of each step is visible to all threads, but if two threads need to execute number++, So this is a total of 6 operation sets, which may be cross-executed, and the result of number may not be expected at the end.

Therefore, for the non-atomic operation of number++, it is recommended to use synchronized:

Synchronized (this) {     number++;   }  

The following code: The result of the last number is not necessarily 500, it is probably smaller than 500 because number++ is not an atomic operation, and volatile does not guarantee visibility

PublicClassvolatiletest {PublicStaticint number = 0;PublicvoidIncrease () {Try{Thread.Sleep (300); }Catch(Interruptedexception e) {//TODO auto-generated Catch blockE.printstacktrace (); } number++; }/***@paramArgs*/PublicStaticvoidMain (string[] args) {Final Volatiletest test = new Volatiletest (); for (int i = 0; i <; I++new Thread (new Runnable () {@Override public void run () {test.increase ();}}). Start (); } //) {Thread.yield ();   "System.out.println (" number is "+ number)}}           

For non-atomic operations such as self-increment, visibility can only be guaranteed in the following ways:

A. Synchronized

B. Reentrantlock

C. Atomicinteger

Synchronized modified as follows:

void Increase () {        try {            thread.sleep (+catch// TODO auto-generated catch block  Synchronized (this) {number++;}}         

Reentrantlock Modify the method as follows:

PublicClassvolatiletest {PublicStaticint number = 0;public lock lock = newpublic void increase () {try {Thread.Sleep (300 ); } catch (Interruptedexception e) {// TODO auto-generated catch Block E.printstacktrace () ; } lock.lock (); try{number++;// This block of code may have an exception in the actual project, so to capture}finally{lock.unlock ();// Use a try finally block to ensure that unlock must execute}} ... } 

Atomicinteger, a class that provides an integer for atomic manipulation. In the Java language, ++i and i++ operations are not thread-safe and, when used, will inevitably use the Synchronized keyword. The Atomicinteger is a thread-safe plus-minus operation interface.

Modify the following:

PackageCom.mooc.test;ImportJava.util.concurrent.atomic.AtomicInteger;PublicClassvolatiletest {Publicstatic Atomicinteger number =New Atomicinteger (0);PublicvoidIncrease () {Try{Thread.Sleep (300); }Catch(Interruptedexception e) {//TODO auto-generated Catch blockE.printstacktrace (); } number.getandincrement ();//Get current value and add 1}/***@paramArgs*/PublicStaticvoidMain (string[] args) {Final Volatiletest test =new Volatiletest (); for (int i = 0; i <; I++new Thread (new Runnable () {@Override public void run () {test.increase ();}}). Start (); } //) {Thread.yield ();   "System.out.println (" number is "+ Number.get ())}}           

5. Application of Volatile

A. Writing to a variable does not depend on the current value

such as self-increment, number = number + 5 (not satisfied)

B. The current volatile variable does not depend on another volatile variable

such as Volatile_var > Volatile_var2 This inequality (not satisfied)

6. Synchronized and volatile comparison

A. Volatile does not require synchronous operation, so it is more efficient and does not block the thread, but the application is relatively narrow

B. Volatile read variable equivalent to locking (that is, enter synchronized code block), and write variable equivalent to unlock (exit synchronized code block)

C. Synchronized can not only guarantee the sharing of variable visibility, but also guarantee the atomicity of the operation in the lock; volatile can only guarantee visibility

Java multi-threaded shared variable control

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.