Java concurrency of volatile two

Source: Internet
Author: User
Tags volatile

Using the Volatilekeyword scene

Volatile variables have synchronized visibility characteristics. But they don't have atomic properties. This means that threads can proactively 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.

So. Using volatile alone is not enough to implement counters, mutually exclusive locks, or classes that have invariant (invariants) associated with multiple variables (such as "Start <=end").
For simplicity or scalability, you might prefer to use volatile variables instead of locks. Some customary usage methods (idiom) are easier to encode and read when using volatile variables rather than locks.

In addition Volatile variables do not cause threads to clog up like locks. Therefore, there are very few scalability issues. In some cases, assuming that the read operation is much larger than the write operation, the volatile variable can also provide performance advantages over the lock.
Conditions for correct use of volatile variables
You can use volatile variables instead of locks in a limited number of situations.

To provide ideal thread safety for volatile variables, the following two conditions must be met at the same time:
(1) The write operation on the variable does not depend on the current value.
(2) The variable is not included in the invariant with other variables.

In fact, these conditions indicate that. These valid values that can be written to a volatile variable are independent of the state of whatever program, and contain the current state of the variable.


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-change-write sequence of operations. Must be run atomically, and volatile cannot provide the necessary atomic properties. Implementing the correct operation requires that the value of X remain constant during operation. Volatile variables do not achieve this. (However, suppose the value is adjusted to be written only from a single thread.) Then the first condition can be ignored.


Most programming scenarios conflict with one of these two conditions, making volatile variables not as universally applicable to thread safety as synchronized.

Performance: Using volatile variables is much simpler than using corresponding locks. On most processor architectures right now. Volatile read operations are very inexpensive-almost the same as non-volatile read operations. The cost of volatile writes is much more than non-volatile write operations, because memory Fence is required to ensure visibility. Even so, the total cost of volatile is still lower than lock acquisition.


Volatile operations do not clog like locks, so. In cases where volatile is safe to use, volatile can provide some scalability characteristics that are better than locks.

The number of read operations is assumed to be much greater than the write operation. Volatile variables can often reduce the performance overhead of synchronization compared to locks.


Several scenarios in Java that use volatile:

1. Status Mark Amount

Volatile Boolean shutdownrequested;...public void shutdown () {shutdownrequested = true;} public void DoWork () {when     (!shutdownrequested) {         //do Stuff    }}
It is very likely that the shutdown () method is called from outside the loop-that is, in a thread-so there is a need to run some kind of synchronization to ensure that the visibility of the shutdownrequested variable is properly implemented. (may be called from a JMX listener, an action listener in the GUI event thread, through RMI, through a Web service, and so on).

However. Writing loops using synchronized blocks is much more cumbersome than using the volatile status flags that are seen in Listing 2. Because volatile simplifies coding, and status flags do not depend on any other state within the program. So this is a good place to use volatile.


A common feature of such a type's status token is that there is usually only one state transition; the shutdownrequested flag is converted from false to true. Then the program stops. Such a pattern can be extended to a state flag that transitions back and forth, but only with the ability to expand (from false to true and then to false) if the conversion period is not detected. In addition Some atomic state transition mechanisms are also required. such as atomic variables.


2 Disposable Security Announcement

Lack of synchronization results in the inability to achieve visibility, which makes it more difficult to determine when to write object references instead of primitive values. In the absence of synchronization, you may encounter an update value for an object reference (written by another thread) and the old value of the state of the object exists at the same time. (This is the root cause of the famous double-check lock (double-checked-locking) problem. In this case, the object reference is read without synchronization. The problem is that you may see an updated reference, but you will still see objects that are not fully constructed through the reference.


One technique for implementing a secure Advertisement object is to define an object reference as a volatile type. Shows a demo sample in which a background thread loads some data from the database during the startup phase.

Other code, when available, checks whether the data was previously published before use.

public class Backgroundfloobleloader {public    volatile flooble theflooble;    public void Initinbackground () {        //do lots of stuff        theflooble = new flooble ();  The only write to theflooble    }}public class SomeOtherClass {public    void DoWork () {while        (true) { c8/>//do some stuff            ... Use the flooble, but only if it's ready            if (floobleloader.theflooble! = null)                 dosomething (Floobleloader.thef looble);}}}    
Assuming that the theflooble reference is not a volatile type, the code in DoWork () is releasing a reference to theflooble. Will get a flooble that is not completely constructed.


One of the prerequisites for this pattern is that the advertised object must be thread-safe. Or a valid immutable object (valid immutable means that the state of the object will never be altered after publication).

A reference to a volatile type ensures the visibility of the object's advertised form, but assumes that the state of the object changes after it is advertised, and that additional synchronization is required.


3. Independent observation

There is also a simple pattern for safe use of volatile: regular "publish" observations for use within the program. For example, if there is an environmental sensor that can feel the ambient temperature. A background thread might read the sensor every few seconds and update the volatile variable that includes the current document. The other thread can then read the variable so that it can see the latest temperature values at any time.
Another application that uses this pattern is the collection of statistical information about the program. The following shows how the authentication mechanism remembers the name of the user who logged in recently. Reuse of Lastuser is used to advertise values for use by other parts of the program.

public class Usermanager {public    volatile String Lastuser;    public Boolean authenticate (string user, string password) {        Boolean valid = passwordisvalid (user, password);        if (valid) {            user U = new User ();            Activeusers.add (u);            Lastuser = user;        }        return valid;}    }
This pattern is an extension of the preceding pattern. Advertise a value for use elsewhere within the program, but unlike the announcement of a one-time event, this is a series of independent events.

This mode requires that the declared value be valid and immutable-that is, the status of the value will not change after it is published. The code that uses this value needs to be clear that the value may change at any time.



4: "Volatile bean" mode

The volatile bean pattern applies to the framework that uses JavaBeans as the "honor structure." In volatile bean mode. JavaBean is used as a container for a set of independent properties that have getter and/or setter methods. The basic principle of the volatile bean pattern is that very many frameworks provide containers for variable data holders (such as HttpSession), but the objects placed in these containers must be thread-safe.
In volatile bean mode, all data members of JavaBean are volatile types, and getter and setter methods must be common--except to get or set corresponding properties, no matter what the logic. Additionally, data members are referenced by the object. The referenced object must be valid and immutable. (This disables properties that have array values, because when an array reference is declared as volatile, there is only a reference, not the array itself, with the volatile semantics).

Invariants or constraints cannot include the JavaBean property for any volatile variable. The demo sample shows a JavaBean that adheres to the volatile bean pattern:

@ThreadSafepublic class Person {    private volatile String firstName;    private volatile String lastName;    private volatile int age;    Public String Getfirstname () {return firstName;}    Public String Getlastname () {return lastName;}    public int getage () {return age;}    public void Setfirstname (String firstName) {         this.firstname = firstName;    }    public void Setlastname (String lastName) {         this.lastname = lastName;    }    public void Setage (int.) {         this.age = age;    }}



Advanced mode of volatile
using volatile in the above patterns is practical and simple. This section describes a more advanced pattern. In this mode, volatile will provide performance or scalability benefits.
The advanced mode of volatile applications is very fragile. As a result, the conditions must be carefully documented, and these patterns are tightly encapsulated, because even very small changes can damage your code. Same. The reason for using more advanced volatile use cases is that it can improve performance. Make sure you're really sure you need to achieve this performance benefit before you start applying advanced mode.

These patterns need to be weighed to give up readability or maintainability in exchange for possible performance gains-if you don't need to improve performance (or you can't prove you need it with a rigorous test program), then this is probably a bad deal. Because you are very likely to lose the candle, the exchange of things than to give up something less valuable.
5. Low-cost read-write lock policy
So far, you should understand that volatile functionality is not enough to implement counters.

Since ++x is actually a simple combination of three operations (read, join, and store), it is possible that multiple threads are likely to lose their updated values if they accidentally attempt to run incremental operations against the volatile counter at the same time.
However, assuming that the read operation is much more than the write operation, you can use both internal and volatile variables to reduce the overhead of the common code path.

The following code shows a thread-safe counter that uses synchronized to ensure that the incremental operation is atomic and uses volatile to guarantee the visibility of the current result. Assume that updates are infrequent. This method achieves better performance 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.

<span style= "FONT-SIZE:18PX;" > @ThreadSafepublic class Cheesycounter {    //employs the cheap read-write lock trick    //all mutative operations Must be do with the ' this ' lock held    @GuardedBy ("This") private volatile int value;    public int GetValue () {return value;}    public synchronized int increment () {        return value++;    }} </span>

This technique is called a "low-cost read-write lock" because you use a different synchronization mechanism for read and write operations. Because the write operation in this example violates the first condition that uses volatile, you cannot use volatile to safely implement counters--you must use locks. However, you can use volatile in a read operation to ensure the visibility of the current value, so you can use the lock for all changes. Use volatile for a read-only operation. Of The lock only accepts one thread at a time to access the value. Volatile agrees to run read operations on multiple threads, so when you use the volatile guarantee to read code paths, you get a higher degree of sharing than running all code paths with locks-like read-write operations. However. Always keep in mind the weaknesses of this pattern: assuming that it goes beyond the most basic application of the pattern, it becomes difficult to combine the two competing synchronization mechanisms.

Conclusion
Volatile variables are a very easy and fragile synchronization mechanism compared to locks. It will provide better performance and scalability than locks in some cases. Assumptions are strictly followed by the use of volatile conditions-that is, the variables are truly independent of other variables and their own values-and in some cases can use volatile instead of synchronized to simplify the code. However. Code that uses volatile is often more prone to error than code that uses locks.

The pattern described in this article covers some of the most common use cases that can replace synchronized with volatile. Following these patterns (not exceeding their limits when using them) can help you to implement most use cases safely. Use volatile variables for better performance.



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

Java concurrency of volatile two

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.