Detailed description of Volatile variables in multiple threads

Source: Internet
Author: User

Java Theory and Practice: using Volatile variables correctly

Original: http://www.ibm.com/developerworks/cn/java/j-jtp06197.html

Summarize:

The lock provides two main features: Mutual exclusion (mutual exclusion) and visibility (visibility). Mutual exclusion allows only one thread to hold a particular lock at a time, so you can use this attribute to implement a coordinated access protocol to shared data so that only one thread can use that shared data at a time. Visibility is more complex, and it must ensure that the changes made to the shared data before the lock is released are visible to the other thread that subsequently acquired the lock-if there is no guarantee of this visibility provided by the synchronization mechanism, the shared variables that the thread sees may be pre-modified or inconsistent values, which can cause many serious problems.

Volatile variable

Volatile variables have synchronized the visibility characteristics, but do not have atomic characteristics (refers to a conforming operation such as i++, for a value of a single operation, such as instantiation and assignment to a long type, has atomic characteristics, that is, the instruction will not be reordered). This means that threads can automatically discover the latest values of volatile variables. Volatile variables can be used to provide thread safety, but can only be applied to a very limited set of use cases: there is no constraint between multiple variables or between the current value of a variable and the modified value. Therefore, using volatile alone is not sufficient to implement counters, mutexes, or any class that has invariant (invariants) associated with multiple variables (for example, "Start <=end").

Conditions for correct use of volatile variables

You can use volatile variables instead of locks in a limited number of situations. For the volatile variable to provide ideal thread safety, the following two conditions must be met:

    • The write operation on the variable does not depend on the current value. (e.g. i++)
    • The variable is not contained in an invariant that has other variables. (for example, the Nether is always less than or equal to the upper bounds)

To illustrate:

The first condition restricts the volatile variable from being used as a thread-safe counter. Although an incremental operation ( x++ ) looks like a separate operation, it is actually a combination of a read-modify-write sequence of operations that must be performed atomically, and volatile does not provide the necessary atomic properties. Implementing the correct operation requires that x the values remain constant during the operation, and the volatile variable cannot achieve this. (However, if you adjust the value to write only from a single thread, the first condition can be ignored.) )

Most programming scenarios conflict with one of these two conditions, making volatile variables not as synchronized universally applicable to thread safety. Listing 1 shows a non-thread-safe numeric range class. It contains an invariant-the nether is always less than or equal to the upper bound.

Listing 1. Non-thread-safe numeric range classes
 @NotThreadSafe public class Numberrange {private int lower, upper;    public int Getlower () {return lower;}    public int Getupper () {return upper;}        public void Setlower (int value) {if (Value > Upper) throw new IllegalArgumentException (...);    lower = value;         } public void Setupper (int value) {if (value < lower) throw new IllegalArgumentException (...);    upper = value; }}

This approach restricts the state variables of the scope, so lower defining the and upper fields as volatile types does not fully implement the thread safety of the class, and thus still requires synchronization. Otherwise, if two threads are executed at the same time with inconsistent values setLower setUpper , then the scope will be in an inconsistent state. For example, if the initial state is, at the (0, 5) same time, thread A is called setLower(4) and thread B is called setUpper(3) , it is clear that the values crossed by these two operations are not eligible, then two threads will pass the check to protect the invariant so that the final range value is (4, 3) -an invalid value. As for other operations on the scope, we need to make setLower() and setUpper() operate atomically--and it is not possible to define a field as a volatile type.

Correct use of volatile patterns

Principle: always keep in mind the limitations of using volatile-the rule that volatile--can be used only when the state is truly independent of other content within the program avoids extending these patterns to unsafe use cases.

Correct use Case 1: (Visibility attribute)

Implementing the canonical use of volatile variables is simply using a Boolean status flag

Volatile Boolean shutdownrequested;...public void shutdown () {shutdownrequested = true;} public void DoWork () {when     (!shutdownrequested) {         //do Stuff    }}

Correct use case 2: (Do not reorder attributes)

Thread-Safe single-case mode

  1. public class Singletonkerrigand {
  2. /**
  3. * Single instance of an object
  4. */
  5. private static Singletonkerrigand instance = NULL;
  6. public static Singletonkerrigand getinstance () {
  7. if (instance = = null) {
  8. Synchronized (Singletonkerrigand.class) {
  9. if (instance = = null) {
  10. Instance = new Singletonkerrigand ();
  11. }
  12. }
  13. }
  14. return instance;
  15. }
  16. }

Other use cases look at the original.

Correct use case 3 (Advanced): low-cost read-write lock policy. (The cost of volatile is synchronized smaller, and the volatile read operation, smaller, it does not contain the operation, almost equal to non-volatile read)

If the read operation is far more than the write operation, you can use both internal and volatile variables to reduce the overhead of the common code path. The thread-safe counters shown in Listing 6 use to synchronized ensure that incremental operations are atomic and use volatile the visibility that guarantees the current results. This approach achieves better performance if the update is infrequent, because the cost of the read path involves only volatile read operations, which is usually better than the overhead of a non-competitive lock acquisition.

public class Cheesycounter {    //employs the cheap read-write lock trick    //All mutative operations must is done WI Th the ' This ' lock held    volatile int value;    public int GetValue () {return value;}    synchronized int increment () {        return value++;    }}

Detailed description of Volatile variables in multiple threads

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.