Java Multithreading Basics (2) __ Multithreading

Source: Internet
Author: User
Tags garbage collection mutex thread class visibility volatile ticket
Daemon Threads

The user thread is the thread that runs in the foreground, and the daemon is the thread that runs in the background. The role of the daemon is to facilitate the operation of other foreground threads , and only if the normal, non-daemon threads are still running, such as a garbage collection thread is a daemon thread. When the VM detects that only one daemon is left, and the user thread has exited, the VM exits, because there is no need to continue running the program without being guarded. if a non-daemon thread is still alive, the VM will not exit .

The daemon thread is not only provided internally by the virtual machine, but the user can also set the daemon itself when writing the program. The user can use the thread's Setdaemon (True) method to set the current thread as the daemon thread.

Although a daemon may be useful, it is important to be careful to ensure that all other non-daemon threads die without any harm due to its termination. Because you can't know if the daemon has completed the expected service task before all the user threads quit running. Once all the user threads have exited, the virtual machine is out of operation. Therefore, do not perform business logic operations (such as reading and writing to data) in a daemon thread. 、

There are a few caveats to note: Setdaemon (true) must be set before calling the thread's start () method, or it will run out of illegalthreadstateexception exceptions. the new thread that is generated in the daemon thread is also the daemon thread. do not assume that all applications can be assigned to a daemon for service, such as read-write operations or computational logic. Thread Blocking

A thread can block four states: When the thread executes Thread.Sleep (), it blocks until the specified millisecond time, or the blocking is interrupted by another thread, and when the thread encounters a wait () statement, it blocks until it is notified (notify ()), Interrupted or passed for a specified number of milliseconds (if the timeout value is set) There are several ways in which the thread blocks with different I/O. A common way is to inputstream the read () method, which blocks until a byte of data is read from the stream, and it can block indefinitely, so it cannot specify a timeout; Threads can also block exclusive access to wait for a lock on an object (that is, blocking when a lock must be acquired for the synchronized statement).

not all blocking states are interruptible, the first two of these blocking states can be interrupted, and the latter two do not respond to interrupts. Synchronized

In concurrent programming, the resources that multithreading concurrently accesses are called critical resources, when multiple threads simultaneously access the object and require the operation of the same resource, splitting the atomic operation may cause inconsistent data or incomplete data, and in order to avoid this, we will take a synchronization mechanism to ensure that in a moment , only one thread is allowed within the method.

The synchronization mechanism implemented using the synchronized modifier is called a mutex mechanism, and the lock it obtains is called a mutex.Each object has a monitor (lock tag) that accesses the resource when the thread owns the lock tag, and enters the lock pool without a lock tag .。 Any object system creates a mutex for it, which is designed to be assigned to threads to prevent the interruption of atomic operations.locks on each object can only be assigned to one thread, so they are called mutexes. about synchronization mechanisms acquiring mutexesIf there are two or more threads within the same method, each thread has its own local variable copy.each instance of a class has its own object-level lock. When a thread accesses an synchronized synchronized code block or synchronization method in an instance object, the thread acquires the object-level lock of the instance, and the other threads need to block the wait if they want to access the synchronized synchronized code block or synchronization method. The object-level lock is released until the previous thread exits from the synchronized code block or method.access to a synchronized code block in a different instance object of the same class without blocking waiting to acquire the object lock, because they get the object-level locks of their respective instances without affecting each other.holding an object-level lock does not prevent the thread from being swapped out, nor does it block other threads from accessing the synchronized code in the same sample object。 When a thread a holds an object-level lock (that is, it enters a synchronized-decorated code block or method), the thread can also be swapped out, and thread B is likely to get the time to execute the code in that object, but it can only execute asynchronous code (not decorated with synchronized). When you execute to the synchronization code, is blocked, the thread planner may then let a thread run, a thread continues to hold the object-level lock, and when a thread exits the synchronization code (that is, the object-level lock is released), the object-level lock is obtained if the B-thread is running at this time. Thus executing the code in synchronized.threads Holding Object-level locks can cause other threads to block outside all synchronized code。 For exampleThere are three synchronized method A,b,c in a class, when thread A is executing method A in an instance object m, it obtains the object level lock, then the other thread executes the code in the same instance object (that is, Object m). is blocked at all synchronized methods, where the method A,b,c is blocked, and when thread a releases the object-level lock, other threads can get the object-level lock by executing the method a,b or code in C. * * using synchronized (OBJ) Synchronized statement blocks, you can get object-level locks on the specified object. **obj is a reference to an object that, if you obtain an object-level lock on an obj object, blocks the wait at its synchronized code until you get the object-level lock on the Obj object when you access the Obj object concurrently. When obj is this, it is the object-level lock that gets the current object. Class-level locks are shared by all samples of a particular class and are used to control concurrent access to static member variables and static methods. The specific usage is similar to the object level lock. Mutual exclusion is a means to achieve synchronization, the critical region, mutual exclusion and semaphore are the main mutually exclusive implementation methods. After the Synchronized keyword is compiled, it isThe synchronization blocks are formed before and after the Monitorenter and monitorexit these two byte code instructions。 According to the requirements of the virtual machine specification, the first attempt to acquire the lock of the object when executing the monitorenter instruction,If you get a lock, add 1 to the lock counter., correspondingly, the lock counter is reduced by 1 when the monitorexit instruction is executed,when the counter is 0 o'clock, the lock is released.。 Because the synchronized synchronization block is reentrant for the same thread, a thread can acquire the mutex of the same object multiple times, and the same mutex is released to the appropriate number of times to release the lock.volatile

before JDK1.2, the Java memory Model implementation always reads variables from main memory (that is, shared memory), and does not require special attention. as the JVM matures and optimizes, it is now important to use the volatile keyword in a multithreaded environment.

under the current Java memory model, threads can store variables in local memory (such as machine registers) instead of reading and writing directly in main memory. this can cause a thread to modify the value of a variable in main memory, while another thread continues to use its copy of the variable value in the register, resulting in inconsistent data.

To solve this problem, you need to declare the variable as volatile (or you can use synchronization), which instructs the JVM that the variable is unstable and is read in main memory every time it is used. In general, in a multitasking environment, variables shared among tasks should be volatile modifiers.

volatile decorated member variables are forced to reread the value of the member variable from shared memory each time it is accessed by the thread. also, when a member variable changes, the thread is forced to write the change value back to the shared memory. So at any given moment, two different threads always see the same value for a member variable.

Volatile is a slightly weaker synchronization mechanism that does not perform a lock operation when accessing volatile variables and does not perform thread blocking, so the Volatilei variable is a more lightweight synchronization mechanism than the Synchronized keyword.

Recommendation: use volatile on a member variable that two or more threads need to access. You do not need to use volatile when the variable you want to access is already in the synchronized code block, or it is a constant.

because the use of volatile masks the necessary code optimizations in the JVM, it is less efficient, so use this keyword only when necessary. Memory Visibility

the functionality of lock (synchronized sync) is not limited to mutex behavior, but there is another important aspect: memory visibility . Not only do we want to prevent a thread from using object state while another thread modifies the state at the same time, but also wants to ensure that when one thread modifies the state of the object, other threads can see the change. And thread synchronization is exactly what it can achieve.

A built-in lock can be used to ensure that a thread can view the execution results of another thread in a predictable way. To ensure that all threads can see the latest values for shared variables, you can add the same lock on all threads that perform read or write operations.

Consider the following code

    public class  Mutableinteger  
    {  
        private int value;  

        public int Get () {return  
            value;  
        }  
        public void set (int value) {  
            this.value = value;  
        }  
    }  

in the preceding code, the Get and set methods access value without synchronizing. If value is shared by more than one thread, if a thread calls set, another thread that is calling get may see the updated value or it may not be visible.

By synchronizing the set and get methods, you can make Mutableinteger a thread-safe class, as follows

    public class  Synchronizedinteger  
    {  
        private int value;  

        public synchronized int get () {return  
            value;  
        }  
        Public synchronized void set (int value) {  
            this.value = value;  
        }  
    

The set and get methods are synchronized, and the same object lock is added, so that the Get method can see the change of value in the Set method, so that each value obtained by the Get method is the most recent values of value. Comparison of two methods of memory visible: lock and volatile variables

difference between lock and volatile variables volatile variable is a slightly weaker synchronization mechanism does not perform a lock operation when accessing a volatile variable and therefore does not block the execution thread. So the volatile variable is a more lightweight synchronization mechanism than the Synchronized keyword. From the perspective of memory visibility, writing the volatile variable is equivalent to exiting the synchronized code block, while reading the volatile variable is equivalent to entering the synchronized code block. If you rely too much on volatile variables to control the visibility of the state in your code, it is often more fragile and more difficult to understand than the code that uses the lock. It should only be used if the volatile variable simplifies the implementation of the Code and validates the synchronization policy. in general, it is safer to use a synchronization mechanism . The locking mechanism (that is, the synchronization mechanism) ensures both visibility and atomicity, while the volatile variable ensures visibility only because a simple variable declared as volatile if the current value is related to the previous value of the variable, then the volatile keyword does not work. This means that the following expressions are not atomic: "count++", "Count = count+1".

You should use the volatile variable when and only if all of the following conditions are true: writing to 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 with other variables. runnable and thread to achieve the difference between multithreading

There are two ways to implement multithreading in Java: To inherit the thread class and implement the Runnable interface, as long as it is multi-threaded in the development of the program, it is always to realize the runnable interface, because the implementation of the Runnable interface has the following advantages over the inheritance thread class: Avoids the limitations of Java's single inheritance features , enhances the robustness of programs, allows code to be shared by multiple threads, and code is independent of data, and a thread area that is suitable for multiple identical program code handles the same resource. Example of selling tickets

Inheritance Thread Implementation

    Class Mythread extends thread{  
        private int ticket = 5;  
        public void Run () {for  
            (int i=0;i<10;i++)  
            {  
                if (Ticket > 0) {  
                    System.out.println ("ticket =" + ticket--)  
    ;  

    }}} public class threaddemo{public  
        static void Main (string[] args) {  
            new Mythread (). Start ();  
            New Mythread (). Start ();  
            New Mythread (). Start ();  
          
    

Results

    Thread-2 Sold ticket = 5
    Thread-1 Sold ticket = 5
    Thread-0 Sold ticket = 5
    Thread-0 Sold ticket = 4
    Thread -1 Sold ticket = 4
    Thread-2 Sold ticket = 4
    Thread-1 Sold ticket = 3
    Thread-0 Sold ticket = 3
    Thread-1 Sol D ticket = 2
    Thread-2 Sold ticket = 3
    Thread-1 Sold ticket = 1
    Thread-0 Sold ticket = 2
    Thread-0 sold T Icket = 1
    Thread-2 Sold ticket = 2
    Thread-2 Sold ticket = 1

As can be seen from the results, each thread sold a separate 5 tickets, that is, the independent completion of the task of buying tickets, but the actual application, such as the railway station ticketing, need multiple threads to work together to complete the task, in this case, that is, multiple threads to buy 5 tickets together.

implement runnable interface implementation

    /**
     * Created by Roger on 2016/8/16.
     * * Public
    class Testrunnable implements Runnable {

        private int ticket = 5;

        @Override public
        Void Run () {for
            (int i=0; i<20; i++) {
                if (Ticket > 0) {
                    System.out.println ( Thread.CurrentThread (). GetName () + "Sold ticket =" + ticket--);
                }
            }

        public static void Main (string[] args) {
            /*new Thread (New Testrunnable ()). Start ();
            New Thread (New Testrunnable ()). Start ();
            New Thread (New Testrunnable ()). Start (); */

            testrunnable testrunnable = new testrunnable ();
            New Thread (testrunnable). Start ();
            New Thread (testrunnable). Start ();
            New Thread (testrunnable). Start ();
        }
    }

Results

    Thread-1 Sold ticket = 4
    Thread-2 Sold ticket = 3
    Thread-0 Sold ticket = 5
    Thread-2 Sold ticket = 1
    Thread -1 Sold ticket = 2

as can be seen from the results, three threads sold a total of 5 tickets, that is, they jointly completed the task of buying tickets, to achieve the sharing of resources.

For more information please refer to Java Multithreading Basics (2)

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.