Reading notes-----Java Concurrent Programming Combat (ii) sharing of objects

Source: Internet
Author: User
Tags volatile

1  Public classnovisibility{2    Private Static BooleanReady ;3    Private Static intNumber ;4    Private Static classReaderthreadextendsthread{5           Public voidrun () {6                 while(!Ready )7 Thread.yield ();8 System.out.println (number);9          }Ten    } One  A      Public Static voidMain (string[] args) { -            NewReaderthread (). Start (); -Number = 42; theReady =true; -     } -}

It is not safe to share access variables between two threads, and the order of execution results is unpredictable.

The Get and set methods that we use are sometimes non-thread-safe

1 @NotThreadSafe2  Public classmutableinteger{3       Private intvalue;4        Public intGet () {returnvalue;}5        Public voidSetintValue) { This. Value =value;} 6}

If a thread calls set, another thread that is calling get may see the updated value value, or it may not see

Turn it into a thread-safe class

 Public class synchronizedinteger{       @GuardBy (privateint  value;         Public synchronized int get () {return  value;}         Public synchronized void Set (int value) {this. Value = value;}}

The meaning of locking is not limited to mutex behavior, but also includes memory visibility. To ensure that all threads can see the latest values for shared variables, all threads that perform read or write operations must synchronize on the same lock.

Volatile variable

Used to ensure that update operations for variables are notified to other threads. Volatile variables can be thought of as a "light synchronized", and volatile variables require less coding and run-time overhead than synchronized blocks, but the functionality they can achieve is only synchronized Part of it.

Volatile variables have synchronized visibility characteristics, but they do not have atomic properties. 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").

For simplicity or scalability, you might prefer to use volatile variables instead of locks. Some idioms (idiom) are easier to encode and read when using volatile variables rather than locks. In addition, volatile variables do not cause threads to block like locks, and therefore are less likely to cause scalability problems. In some cases, if the read operation is much larger than the write operation, the volatile variable can also provide a performance advantage over the lock.

But if you rely on volatile variables in your code to control the visibility of States, it is often more brittle and more difficult to understand than the code that uses locks.

You should use volatile variables only if they simplify code implementations and validate synchronization policies. If you need to make complex judgments about visibility when validating correctness, do not use volatile variables. The correct use of volatile variables includes ensuring the visibility of their own state, ensuring the visibility of the state of the objects they reference, and marking the occurrence of some important program life-cycle events (for example, initialization or shutdown)

Typical usage: Check a status token to determine whether to exit the loop.

volatile Boolean asleep,    .....  while (! asleep)        Countsomesheep ();

Volatile is not sufficient to ensure the atomicity of the increment operation.

The locking mechanism ensures that both visibility and atomicity can be ensured. Volatile variables can only ensure visibility.

Volatile variables should be used only when and only if the following conditions are met

    • The write operation on a variable does not depend on the current value of the variable, or you can ensure that only a single thread updates the value of the variable
    • The variable is not included in the invariant condition with variables of other states
    • No lock required when accessing variables
release and EscapeThe so-called release object is to enable an object to be used by code outside the current scope. The so-called Escape is a false release situation, when an object has not yet been constructed, so that it is seen by other threads, this situation is called the object escape. In our daily development, we often publish objects, such as a reference to an object through a non-private method of a class, or to publish an object through a public static variable. As shown in the following code:
1 classunsafestates{2     PrivateString[] states={"AK", "AL"}; 3      PublicString[] GetStates () {returnstates;} 4      Public Static voidMain (string[] args) {5Unsafestates safe =Newunsafestates (); 6 System.out.println (arrays.tostring (Safe.getstates ()));7Safe.getstates () [1] = "C"; 8 System.out.println (arrays.tostring (Safe.getstates ()));9    } Ten}

Output [AL,KL] [al,c] The above code publishes the domain of the class through the public access level, which can be accessed by any thread outside the class so that the publication object is unsafe, because we cannot assume that other threads do not modify these fields, resulting in a class state error. There is also an escape that occurs when the object is constructed, which causes the class's this reference to escape, causing the thread to see an incomplete constructed object, as shown in the following code:
 Public classescape{Private intThiscanbeescape = 0;  PublicEscape () {NewInnerclass (); }     Private  classInnerclass { PublicInnerclass () {//Here you can refer to escape's private variable in advance before the escape object finishes constructingSystem.out.println (Escape. This. Thiscanbeescape); }     }      Public Static voidMain (string[] args) {NewEscape (); } }
An instance of the inner class above contains a reference to the enclosing instance, so that it will be published if the object is not properly constructed, possibly with an unsafe factor. An error that causes this reference to escape during construction is to start a thread in the constructor, either implicitly starting the thread or explicitly starting the thread, causing the this reference to escape, and the new thread will always see it before the owning object is constructed. So if you want to create a thread in the constructor, do not start it, but use a proprietary start or Initialize method to unify the boot thread. We can use factory methods and private constructors to perform object creation and listener registration so that incorrect creation can be avoided.  Remember, our goal is that you cannot publish an object until it is constructed. The right way
1  Public classsafelistener{2     Private FinalEventListener Listener;3     4      PrivateSafelistener () {5Listener =NewEventListener () {6                     Public voidonEvent (Event e) {7 dosomething (e);8                   }9              }Ten       } One  A        Public StaticSafelistener newinstance (EventSource source) { -Safelistener safe =NewSafelistener (); - Source.registerlistener (safe.listener); the               returnsafe; -      } -}
Do not use this escape during the construction process. The constructor can save the this reference somewhere, as long as the other thread does not use it before the constructor finishes. Thread Closure1. The stack is closed. Even with local variables, the base type of local variables must not break the stack closure. Because no method can obtain a reference to a base type, it ensures that a local variable of the base type is always enclosed within the thread. Additional action is required to prevent the referenced object from escaping when the stack enclosing the object reference is maintained. The 2.ThreadLocal class enables a value in a thread to be associated with the object that holds the value. Threadlocal provides a get and set method for each thread that uses the variable to have a separate copy. Threadlocal objects are typically used to prevent the sharing of mutable single-instance variables (Singleton) or global variables. Example:
1 Private StaticThreadlocal<connection>Connectionholder2=NewThreadlocal<connection>(){3            PublicConnection InitialValue () {4                 returndrivermanager.getconnection (db_url);5          }6      };7  Public StaticConnection getconnection () {8       returnconnectionholder.get ();9}

Save the JDBC connection to the Threadlocal object, calling the Get method so that each thread has its own copy of the connection.

Threadlocal<t> can be viewed as map<thread,t> objects. These thread-specific values are saved in the thread object, and when the thread terminates, the values are garbage collected.

Non-denaturingImmutable objects must be thread-safe. Immutable objects must meet the following conditions: 1. After an object is created, its state (member variable) cannot be modified. 2. All fields of the object are final Type 3. The object is created correctly (this reference does not escape) example:
@Immutable Public Final classthreestooges{Private FinalSet<string> stooges =NewHashset<string>();  Publicthreestooges () {Stooges.add ("Moe"); Stooges.add ("Larry"); Stooges.add ("Ted."); }     Public BooleanIsstooge (String name) {returnstooges.contains (name); }}

Immutability does not mean that all fields of an object are declared as final, even if all the fields in the object are final types, the object can still be mutable, because references to mutable objects can be persisted in the final field.

After an object is created (by constructing a method) regardless of whether the object is non-violent (without reflection), the state of the object (the value of the member variable) does not change, then the object is immutable, and the corresponding class is a non-mutable class, which is okay with final decoration, final The decorated class is to prevent this class from being inherited.

Final field

The final field cannot be modified (although the object is still modifiable if the final field points to an immutable object), but it also has special semantics in Java memory mode. The final domain makes it possible to ensure that security is initiated, and the initialization security allows the immutable objects to be freely accessed and shared without needing synchronization.

As in "declaring all domains private, unless they require greater visibility," it is a good practice to declare all fields as final unless they are mutable.

Example: Publishing an immutable object using volatile

The following is an immutable object, in which the state is copied (when used) out (when it is in use). Because the BigInteger is immutable, So the arrays.copyof is used directly to copy it, and if the state is not the object of the immutable object, it cannot be used because the outside world can modify the object that the state directs, if it can only be copied using new or deep cloning technology.

@ImmutableclassOnevaluecache {Private FinalBigInteger Lastnumber; Private Finalbiginteger[] lastfactors;  PublicOnevaluecache (BigInteger i, biginteger[] factors) {Lastnumber=i; Lastfactors=arrays.copyof (factors, factors.length); }      Publicbiginteger[] Getfactors (BigInteger i) {if(Lastnumber = =NULL|| !lastnumber.equals (i))return NULL; Else            returnarrays.copyof (lastfactors, lastfactors.length); }}

The following is the beginning of the release of the immutable object, where volatile plays a key role, if not, even if Onevaluecache is immutable, its newest state cannot be visible to other threads.

@ThreadSafe Public classVolatilecachedfactorizerImplementsServlet {Private volatileOnevaluecache cache =NewOnevaluecache (NULL,NULL);//This is a security release .      Public voidService (ServletRequest req, Servletresponse resp) {BigInteger i=extractfromrequest (req); biginteger[] Factors=cache.getfactors (i); if(Factors = =NULL) {Factors=factor (i); //because the cache is volatile, the latest value can immediately make other threads visibleCache =NewOnevaluecache (i, factors);    } encodeintoresponse (resp, factors); }}

Immutable objects and initialization security

The Java memory model provides a special guarantee of initialization security for shared immutable objects, that is, the object cannot be referenced by the outside world until it is fully initialized.

Immutable objects can still be accessed securely even if the publication object reference is not used in synchronization. For the assurance of this initialization security, all the immutable conditions should be met: the non-modifiable state, all fields are final type, and the correct constructs.

Immutable objects are used safely for any thread without additional synchronization, or even when they are released.

mutable objects and Security releases

If an object is not immutable, it must be published securely, and usually both the publishing thread and the consumer thread must be synchronized. We want to make sure that the consumer thread can see the state of the object at the time of release.

In order to safely publish an object, the object's reference and the state of the object must be visible to other threads at the same time. A properly created object can be safely published with the following conditions:

1. Initialize object reference by static initializer;

2. Store its references in a volatile domain or atomicreference;

3. Store its references in the final domain of the object that is created correctly;

4, or store its references in a domain that is properly protected by the lock.

The container in thread safety provides a thread-safe guarantee that complies with the last requirement above.

In general, the simplest and safest way to publish a statically created object is to use a static initializer:

public static Holder Holder = new Holder (42);
Static initializers are performed by the JVM at the initial stage of the class, and because of the internal synchronization of the JVM, the mechanism ensures that objects initialized in this manner can be safely published.

Object variability and security publishing

The requirements for publishing an object depend on the variability of the object:

1, immutable objects can be published by any mechanism;

2, high-efficient immutable objects (refers to the object itself is variable, but as long as the post-release state is no longer modified) must be safe to publish;

3, the variable object must be safe to publish, at the same time must be thread-safe or lock-protected;

 

Reading notes-----Java Concurrent Programming Combat (ii) sharing of objects

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.