java--Multithreading Summary, threadlocal/volatile/synchronized/atomic keyword __java

Source: Internet
Author: User
Tags thread class volatile

When the thread is created and started, it either goes into execution or is not always executing, and in its lifecycle is new, Ready (Runnable), run (Running '), blocked (Blocked), and ".", and " The five states of Death (Dead). After the thread is created, it is not possible to occupy the CPU running independently, and it needs to switch between multiple threads, so most of the time is switched between running and blocking.

Thread classes and the methods associated with these four states:

    Start thread public
    void Start ();
    public void Run ();

    Suspend and wake thread public
    void Resume ();     The use of public
    void suspend () is not recommended;    Public
    static void sleep (long Millis) is not recommended;
    public static void sleep (long millis, int nanos);

    Terminate thread public
    void Stop ();       The use of public
    Void interrupt () is not recommended;

    Get thread state public
    Boolean isAlive ();
    public boolean isinterrupted ();
    public static Boolean Interrupted ();

    Join method public
    void Join () throws interruptedexception;
Communication between Threads

1, waitand notify must cooperate with synchronized keyword use

2. when the Wait method is invoked, the synchronized synchronized object lock is freed and the Notify method does not release the lock one, new, and ready state of the synchronized synchronized object

(1) When a thread is created with the new keyword, the thread is in a new state;
(2) when the start () method is invoked, the thread enters the ready state. When the runtime is not immediately accessible, wait for the scheduling of the thread scheduler in the JVM.
Note: the start () method can be invoked only on threads that are in the new state, or an exception is thrown.
   second, running and blocking states

(1) If the thread in the ready state obtains the CPU, the Run method is executed and is in a running state. When the allotted time runs out, it enters the ready state and waits for the next time to be allocated to the CPU to enter the running state.
(2), the thread will enter a blocking state if:
1), the thread calls the sleep () method to voluntarily discard the occupied processor resources
2), the thread calls a blocking Io method, and the thread is blocked when the method returns
3), the thread is trying to get a sync monitor, but the Sync monitor is being held by another thread.
4), ready to wait for a notice (notify)
5), the thread has called the thread's suspend () method to suspend the thread. This method is apt to cause deadlock and should be avoided as far as possible.
A program that enters a blocking state can revert to the ready state while waiting for the resource to be allocated to the running state when it encounters the following conditions:
1), the thread that calls the sleep () method passes the specified time.
2), thread-invoked blocking IO method has returned
3), the thread succeeded in obtaining the synchronization monitor to obtain
4, the thread is waiting for a notification, the other thread issued a notification (signal)
5), the suspended state of the thread was called resume () recovery method III, Thread death

(1), run () or call () method execution completed, thread normal end;
(2), the thread throws an exception or error;
(3) Directly call the Stop () method of the thread to end the thread-the method is easy to cause deadlock and is not recommended.
Note: When the main thread ends, the other threads do not end with any effect. Once the child thread starts up, he has the same status as the main thread, and he is not affected by the main thread.
To test whether a thread is dead, you can invoke the IsAlive method of the Thread object, which returns True when the thread is in a ready, running, blocking 3 state, and returns False when the thread is in a new, dead 2 state.
Note: Do not attempt to call the start () method on a dead thread to restart it, and the thread cannot be executed again as a thread. The Start method can be used only for threads that are in the new state, and only once. Iv. three ways to terminate a thread

There are three ways to terminate the thread.

1, the use of exit flags, so that the normal exit of the thread, that is, when the Run method is complete after the thread terminated.

public class Threadflag extends Thread
{public
    volatile Boolean exit = false;

    public void Run ()
    {while
        (!exit);
    }
    public static void Main (string[] args) throws Exception
    {
        Threadflag thread = new Threadflag ();
        Thread.Start ();
        Sleep (5000); Main Thread Delay 5 sec
        thread.exit = true;  Terminate Thread Threads
        thread.join ();
        SYSTEM.OUT.PRINTLN ("Thread exit!");
    }

An exit flag exit is defined in the code above, and when Exit is true, the while loop exits, and exit defaults to False. When you define exit, you use a Java keyword volatile, which is designed to synchronize exit, which means that only one thread can modify the exit value at the same time.

2. use the Stop method to force the termination of the thread (this method is not recommended, as stop and suspend, resume, will release all of the monitor, resulting in unpredictable results.) We rarely want a thread to stop immediately, and if the thread is canceled while the update is in progress, the program data structure may be in an inconsistent state.

3. use the interrupt method to disconnect the thread .
There are two methods in the thread class that can determine whether a thread is terminated by the interrupt method.
① static method Interrupted ()
② non-static method isinterrupted (),
The difference between the two methods is that interrupted is used to determine whether the current line is interrupted, and isinterrupted can be used to determine whether other threads are interrupted.

When another thread interrupts a thread by calling Thread.Interrupt (), the following two conditions occur:
① if the thread is executing a low-level interruptible blocking method, such as Thread.Sleep (), Thread.Join (), or object.wait (), it will unblock and throw interruptedexception.
②interrupt () simply sets the interrupt state of the thread. The code that runs in the interrupted thread can then poll the interrupt state to see if it has been requested to stop what is being done. The interrupt state can be read by thread.isinterrupted () and can be read and purged by an operation named Thread.interrupted ().

Interrupts are a collaborative mechanism. When one thread interrupts another, the interrupted thread does not have to stop what is being done immediately. Instead, interrupts are politely asking another thread to stop what it is doing when it is willing and convenient. Some methods, such as Thread.Sleep (), take such requests seriously, but each method does not necessarily respond to interrupts. For interrupt requests, methods that do not block but still take a long time to execute can poll the interrupt state and return early when interrupted. You can ignore interrupt requests at will, but doing so affects the response.
One of the benefits of disruptive collaboration features is that it provides greater flexibility to securely construct a removable activity. We rarely want an activity to stop immediately, and if the activity is canceled while the update is in progress, the program data structure may be in an inconsistent state. Interrupts allow an activity to be canceled to clean up work in progress, restore invariants, and notify other activities that it will be canceled before terminating.

The sample code is as follows:

public void Run () {while
    (true) {
        if (Thread.CurrentThread (). isinterrupted ()) {//②
            System.out.println () Interrupted ");
            break;
        try {
            thread.sleep;
        } catch (Interruptedexception e) {//①
            System.out.println ("interrupted when Sleep ");

            /**
             *  When a blocking method detects an interrupt and throws a interruptedexception, it clears the interrupt state.
             *  If you catch a interruptedexception but can't throw it back, you should keep the evidence of the interruption, * so that the higher-level  code in the call stack can know the interrupt and respond to the interrupt.
             *  This task can be interrupt () to "re-interrupt" the current thread to
             complete
            ///capture interruptedexception after the recovery of the interrupt state
            Thread.CurrentThread (). interrupt (); ②} ...

    }

Java Theory and Practice: dealing with the use of join methods in interruptedexception

The function of the

Join method is to make the thread that executes asynchronously into synchronous execution. That is, when the start method of the thread instance is invoked, the method returns immediately, and if you need to use a value computed by this thread after calling the Start method, you must use the Join method. If you do not use the Join method, you cannot guarantee that the thread will run out when a statement after the Start method is executed. After the Join method is used, the program does not go down until the thread exits.

public class Jointhread extends Thread {public static int n = 0;
    Static synchronized Void Inc () {n++; 
                public void Run () {for (int i = 0; i < i++) try {Inc ();  Sleep (3);                                      
    Delay 3 Millisecond} catch (Exception e) {} In order to make the results of the run more random public static void Main (string[] args) throws Exception {Thread threads[] = new thread[
        100];
        for (int i = 0; i < threads.length i++)//Establish 100 threads threads[i] = new Jointhread ();
        for (int i = 0; i < threads.length i++)//Run the 100 Threads Threads[i].start () that have just been established; if (Args.length > 0) for (int i = 0; i < threads.length; i++)//100 threads are executed and continue Threa
        Ds[i].join ();
    System.out.println ("n=" + JOINTHREAD.N); }
}

As the example above: 100 threads are established, each thread increases the static variable n by 10. If you output n after all 100 threads are executed, this n value should be 1000. vi. Use the volatile keyword carefully

The volatile keyword is used to declare simple type variables, such as int, float, Boolean, and so on. If these simple data types are declared as volatile, you can guarantee the visibility of variables between threads. Operations on variables become atomic levels. But there is a certain limit to this. For example, the n in the following example is not an atomic level:

public class Jointhread extends Thread
{public
    static volatile int n = 0;

    public void Run ()
    {for
        (int i = 0; i < i++)
            try
            {
                n = n + 1;
                Sleep (3); Delay 3 Millisecond
            }
            catch (Exception e)
            {
            }
    } public

    static void Main (string[] args) in order to make the results of the run more random Throws Exception
    {

        Thread threads[] = new thread[100];
        for (int i = 0; i < threads.length i++)
            //Establish 100 threads
            threads[i] = new Jointhread ();
        for (int i = 0; i < threads.length i++)
            //Run the 100 Threads
            Threads[i].start () that have just been established;
        for (int i = 0; i < threads.length i++)
            //100 threads are executed to continue
            threads[i].join ();
        System.out.println ("n=" + JOINTHREAD.N);
    }

If the operation of N is atomic, the result of the final output should be n=1000, and when the area code is executed, many times the output of n is less than 1000, indicating that N=n+1 is not an atomic-level operation.

n=n+1/n++ The cause of the non-atomic nature.
n=n+1/n++ is just a statement and how to give the CPU to other threads during execution. This is just a superficial phenomenon, n++ is not a language after being compiled into an intermediate language (also called a bytecode) by the Java compiler.
Java source code:

public void Run ()
{
    n++;
}

The Compiled intermediate language code:

  001 Public  Void Run ()
  002  {
  003      aload_0         
  004 DUP 005      GetField
  006      iconst_1        
  007      iadd            
  008      Putfield 009 return          
  010  }

This involves a problem with a Java memory model.

The Java memory model is divided into the primary and the working storage areas. The primary store holds all instances of Java. That is, after we use new to create an object, the object and its internal methods, variables, and so on are stored in this area, and the N in the Jointhread class is stored in the region. The primary store can be shared by all threads. The work store is the line stacks we talked about, and in this area we keep the variables defined in the Run method and the method called by the Run method, which is the method variable. When a thread modifies a variable in the primary store, it does not modify the variables directly, but instead copies them to the current thread's working store, overwriting the corresponding variable value of the primary store after the modification is complete.

After learning the Java memory model, it is not difficult to understand why n++ is not an atomic operation. It must pass through a copy, plus 1 and overwrite process. Therefore, it is prudent to use the volatile keyword, not as long as the simple type variable uses the volatile modifier, all operations on this variable are atomic, and when the value of the variable is determined by its own previous decision, such as N=n+1, n++, the volatile keyword will fail, The operation of the variable is atomic if it is independent of its previous value, such as n = m + 1, which is the original level. So in the use of volatile key must be cautious, if they are not sure, you can use synchronized to replace volatile.

To solve this problem, there are two options:
1, the traditional method: the use of a method to synchronize N, that is, at the same time only one thread operation N, which is also known as the atomic operation of N. The code is as follows:

public class Jointhread extends Thread {public static int n = 0;
    public static synchronized Void Inc () {n++;  public void Run () {for (int i = 0; i < i++) try {Inc ();
                n = n + 1 changed to Inc (); Sleep (3); Delay 3 Millisecond} catch (Exception e) {}} public static voi in order to make the results of the run more random
        D main (string[] args) throws Exception {Thread threads[] = new THREAD[100];
        for (int i = 0; i < threads.length i++)//Establish 100 threads threads[i] = new Jointhread ();
        for (int i = 0; i < threads.length i++)//Run the 100 Threads Threads[i].start () that have just been established;
        for (int i = 0; i < threads.length i++)//100 threads are executed to continue threads[i].join ();
    System.out.println ("n=" + JOINTHREAD.N); }
}

2, using the Atomicinteger object to define N ThreadLocal, Volatile, synchronized, atomic their respective application scenarios

This paper is more clear: http://blog.csdn.net/u010687392/article/details/50549236

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.