Java Thread (ii)-Thread safety

Source: Internet
Author: User

Preface:The core of writing thread-safe code is to manage state-access operations, especially access to shared and mutable states. When multiple threads access the same mutable state variable without proper synchronization, the program will have an error and there are three ways to fix the problem:
    1. Do not share this state variable between threads
    2. Modifying a state variable to a variable that is immutable
    3. Use synchronization when accessing state variables

Definition of thread safety:This class is thread-safe when multiple threads access a class, regardless of how the runtime environment is scheduled or how those threads will be executed alternately, and if no additional synchronization or co-operation is required in the keynote code, and this class can behave correctly. What is the correct behavior of the class? It does not violate the various invariance conditions of the constrained object state and the various posterior conditions that describe the result of the object operation.
stateless objects must be thread-safe@ThreadSafepublic class Statelessfactorizer implements servlet{
Public
void Service (ServletRequest Req,servletresponse resp) {
BigInteger i = extractfromrequest (req);
biginteger[] factors = factor (i);
Encodeintoresponse (resp,factors);
The stateless object is thread-safe because the behavior of the thread accessing the stateless object does not affect the correctness of the operation in other threads.
Atomic nature:In concurrent programming, incorrect results due to improper execution of timing are a very important situation, called race conditions. Example: @NotThreadSafepublic class Unsafecountingfactorizer implements Servlet {
Private Long Count = 0;public long GetCount () {return count;} public void Service (ServletRequest req, Servletresponse resp) {
BigInteger i = extractfromrequest (req);
biginteger[] factors = factor (i);
++count;
Encodeintoresponse (resp,factors);
}
}
The above Unsafecountingfactorizer class is concurrent thread-safe because of the ++count, which is a "read-modify-write" sequence of operations, and its results depend on the previous state.     When a thread executes a step in ++count, it may be interrupted by another thread, so when multiple threads are accessing the code concurrently, it can cause serious data integrity problems for the object. The most common type of race condition is the "check then Act" operation, which determines the next action through a potentially defunct observation. And a common read-modify-write operation.It is often a common practice to convert composite operations that cause race conditions into atomic operations to ensure thread safety, locking. In the case of a single state, for read modify write operations, you can use some of the facilities in the atomic package to guarantee thread safety for composite operations, such as Atomiclong. @ThreadSafepublic class Unsafecountingfactorizer implements Servlet {Private final Atomiclong count = new Atomiclong (     0);     Public long GetCount () {return count.get ();}          public void Service (ServletRequest req, Servletresponse resp) {BigInteger i = extractfromrequest (req);          biginteger[] factors = factor (i);          Count.incrementandget ();     Encodeintoresponse (resp,factors); }}
Locking mechanism:     When a state variable is added to a servlet, the state of the servlet can be managed through a thread-safe object to maintain thread security for the servlet.     Is it enough to add more than one thread-safe state variable when a class contains multiple states? The following example assumes that to improve performance for the factorization of a servlet, when two successive requests are factoring the same values, the previous calculation can be used directly without recalculation.     @NotThreadSafepublic class Unsafecacheingfactorizer implements Servlet {     private final atomicreference<biginteger> lastnumber = new atomicreference<biginteger> ();     private Final atomicreference<biginteger[]> lastfactors = new atomicreference<biginteger[]> ();     public long GetCount () {return count.get ();}      public void Service (ServletRequest req, Servletresponse resp) {          Bigi Nteger i = extractfromrequest (req);          if (I.equals (Lastnumber.get ())) {    &NBSP ;          encodeintoresponse (Resp,lastfactors.get ());         } else {& nbsp              biginteger[] factors = factor (i);               lastnumber.set (i);               lastfactors.set (factors);  & NBsp            encodeintoresponse (Resp,lastfactors.get ());         }      }}
One of the invariance conditions of Unsafecachingfactorizer is that the product of the cache factor in lastfactors should be equal to the value cached in the Lastnumber. The servlet above is correct only if it ensures that the invariant condition is not compromised. The fact is that although the set method is atomic, it is still not possible to update Lastnumber and lastfactors at the same time, and we cannot guarantee that we will get two values at the same time.When a class contains multiple state variables, the consistency of these state variables should be ensured. To maintain state consistency, you need to update all related state variables in a single atomic operation. Then you need to use the lock.       Built-in Lock: The Synchronized method takes a class object as a lock. Each Java object can be used as a lock that implements synchronization, which is called a built-in lock or a monitoring lock. The thread automatically obtains the lock before it enters the synchronization code block, and the lock is released when the synchronization code block exits. Java's built-in lock is equivalent to a mutex, which means that only one thread can hold this lock at most.       Use synchronized to modify the above example:      @ThreadSafepublic class Synchronizedfactorizer Implements Servlet {      @GuardedBy ("This") private final BigInteger lastnumber;     @ Guardedby ("This") private final biginteger[] lastfactors;     public synchronized void service ( ServletRequest req, Servletresponse resp) {          BigInteger i = extractfromrequest (req); &nbsp ;         if (I.equals (lastnumber)) {               encodeintores Ponse (resp,lastfactors);         } else {                biginteger[] factors = factor (i);               lastnumber = i;    &NBSP ;     &NBSp    lastfactors = factors;               encodeintoresponse (resp, factor s);         }     }}      here, while ensuring thread safety, concurrency is minimized, and we will continue to improve.       Re-entry: In Java, the built-in lock is reentrant, so if a thread tries to acquire a lock that is already held by itself, the request succeeds. "Reentrant" means that the granularity of the operation that acquires the lock is "thread", not "call".       Example: if the built-in lock is not reentrant, then this code will have a deadlock
public class Widget {public synchronized void dosomething () {...} }public class Loggingwidget extends Widget {public synchronized void dosomething () {... super.d     Osomething (); }}
to protect the state with a lock:For mutable state variables that may be accessed concurrently by multiple threads, the same lock is required to access it, in which case we call the state variable to be protected by this lock.     Each shared and mutable variable should be protected by only one lock, so that the maintainer knows which lock it is. For each invariant condition that contains multiple variables, all of the variables involved need to be protected by the same lock, making it impossible for other threads to break the integrity conditions here.
activity and performance: do not hold a lock when the execution takes a long time to calculate or an operation that may not be completed quickly (for example, network IO or console io). Usually we can improve the concurrency of the program by narrowing the synchronization code, but judging the reasonable size of the synchronization code block requires a tradeoff between the various design requirements, including security, which must be met, simplicity, and performance.in general, there is a mutual constraint between simplicity and performance. When implementing a synchronization strategy, be sure not to blindly sacrifice simplicity for performance (which could compromise security). In the Synchronizedfactorizer class we used before, the service is a synchronized method, so only one thread can execute each time, which violates the intent of the servlet framework, concurrency is 0, even if there are multiple CPUs,     The latter servlet request also waits for the previous request to complete before proceeding to the next step. Below we will reduce the scope of the synchronization code block, separate the calculation steps from synchronization, and use the same lock to protect the class's invariant conditions. @ThreadSafepublic class Cachedfactorizer implements Servlet {
@GuardedBy ("This") private final BigInteger Lastnumber, @GuardedBy ("This") private final biginteger[] lastfactors; public void Service (ServletRequest req, Servletresponse resp) {
BigInteger i = Extractfromrequest (req);
biginteger[] factors = null;
synchronized (this) {
if (i.equals (Lastnumber)) {
factors = Lastfactors.clone ();
}
if (factors = = null) {
biginteger[] factors = factor (i);
synchronized (this) {
lastnumber = i;
lastfactors = Factors.clone ();
      }
}
Encodeintoresponse (resp,lastfactors);
}
}

Java Thread (ii)-Thread safety

Related Article

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.