[Java Concurrency] offer 11.P6 pass by because I do not understand the principle of synchronized


use

synchronized keyword is one of the common means of concurrent programming thread synchronization, synchronized pessimistic locking, and its role is threefold:

Mutually exclusive: to ensure mutually exclusive access thread synchronization generation lock is automatically released, with a plurality of threads operating code or function blocks must acquire the lock queue,
visibility: modify the shared variables to ensure timely visible thread to acquire the lock operation is completed the data will be flushed to the shared memory
ordering: effectively solve the problem of reordering, its use also has three:
a modified example of the method
modifying a static method of
modifying block
1. the modified example of a method

synchronized keyword in front of the role of the method for locking method, in fact, this is the default lock object.

class Thread1 the implements the Runnable {public
    // shared resource (critical resource)
    static int I = 0;
    // if the key is not synchronized, the output is less than 20000
    public synchronized void Increase () {
        I ++;
    }
    public void RUN () {
        for (int J = 0; J <10000; J ++) {
            Increase ();
        }
    }
    public static void main (String [] args) throws InterruptedException {
        Thread1 T = new new Thread1 ();
        the Thread T1 = new new the Thread (T);
        the Thread T2 = the thread new new (T);
        t1.start ();
        t2.start ();
        t1.join (); // wait for the main thread t1 finished
        t2.join (); // wait for the main thread t2 finished
        System.out. the println (I);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23


2. Modified static method

synchronized or modification on the method, but the modification is a static method, equivalent to the Class object is locked,

    Thread1 class {public
    // shared resource (critical resource)
    static int I = 0;

    // If not synchronized keyword, output is less than 20000
    public static void synchronized Increase () {
        I ++;
    }

    public static void main (String [] args) throws InterruptedException {
        the Thread T1 = new new the Thread (new new the Runnable () {
            public void RUN () {
                for (int J = 0; J <10000; J ++) {
                    Increase ();
                }
            }
        });
        the Thread new new the Thread T2 = (the Runnable new new () {
            @Override
            public void RUN () {
                for (int J = 0; J <10000; J ++) {
                    Increase ();
                }
            }
        });
        t1.start () ;
        t2.start ();
        t1.join (); // wait for the main thread t1 finished
        t2.join (); // wait for the main thread is finished t2
        System.out.println(i);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32


3. The modified block

For usage is to modify the parameters modified in synchronized intervals with the functions that, compared with the lock function of this range is smaller, you can specify what the object lock.

class Thread1 the implements the Runnable {public
    // shared resource (critical resource)
    static int I = 0;

    @Override
    public void RUN () {
        for (int J = 0; J <10000; J ++) {
            // get String class lock
            the synchronized (String.class) {
                I ++;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread1 t = new Thread1();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

to sum up:

Examples of modified method synchronized, multi-threaded concurrent access, only one thread to enter, obtain an object built-in lock, other threads are blocked waiting for, but in the meantime the thread can still access other methods.
synchronized modification of static methods, multi-threaded concurrent access, only one thread to enter, obtain class lock, other threads are blocked waiting for, but in the meantime the thread can still access other methods.
Modified synchronized code block, multi-threaded concurrent access, only one thread to enter, in accordance with brackets or class object, the corresponding object class locks or built-in lock
for each class has a class locks, each class objects also have a built-in lock, they interfere with each other, meaning that one thread can obtain the lock and built-in locks and class to instantiate objects, when the threads access method synchronzied non-modified, does not need to acquire a lock, So no obstruction.
The tube

The tube (in English: Monitors, also known as a monitor) is very important concept in the operating system, the tube actually refers to the management of shared variables during the operation and management of shared variables. Intermediaries play a little mean, a bunch of objects pipe process management, multiple threads in the same time only one thread to access these things.

The tube can be seen as a software module, which is shared for these variables and shared variables packaging operation to form a functional module having a certain interface, process the tube can call to implement concurrency control process level.
Process can only have exclusive use of the tube, that is, when a process using the tube, another process must wait. After a process finished using the tube, it must release the tube and a process to wait for a wake-up tube process.
The tube is relatively simple to solve the problem of mutual exclusion, the operation of the shared variables and shared variables are encapsulated in a class

When a thread A and thread B need to get a shared variable count, you need to call the get and set methods, and get and set methods is to ensure mutually exclusive, only one thread to ensure that each visit.
Distribution manager, every part of a second-hand housing intermediary management,

Mediation is the tube.
A plurality of second-hand houses are an intermediary management, process management is a tube with multiple system resources.
Multiple clients is equivalent to multiple threads.
The underlying principle Synchronzied

Object header parsing

We know that an object in the Java heap area is created in the JVM memory area, after the object is created consists of three parts.

It features three parts as follows:

Padding data: Since the virtual machine start-request object address must be an integer multiple of 8 bytes. Padding data need not be present, only for byte alignment.
Examples of variables: storing attribute information such as data, attribute information including the parent class, this memory 4-byte aligned.
Object header: includes two parts
Klass Point (pointer type): the object is a pointer to its class metadata, the virtual machine is determined by the pointer which is an instance of the object class.
Mark Word (marker fields): This section for storing operating data of the object itself, such as a hash code, the GC generational age, lock status flags, pointers, etc. locks, which are part of the data size in 32bit and 64bit virtual machine is a 32bit and 64bit, taking into account the space efficiency of the virtual machine, Mark Word is designed as a non-fixed data structures to store as much information in a very small space, it will be multiplexed according to their state of the object storage space ( Similarly with ConcurrentHashMap in the flag), the details as shown below:
mark Word state represents a bit as follows:

Whether or synchronized code block modification method, synchronization is achieved by holding a modified lock of the object, whether the object is synchronized lock object header Mark Word. Lightweight and biased locking which locks after Java6 of synchronized lock to optimize the new addition, here we analyze heavyweight lock is often said synchronized object lock, the lock flag is 10, which is a pointer to the object monitor (also known as the tube monitor or lock) the start address. Each object there is a monitor associated with it.

 

Disassembly View

Former monitor analysis object we first block what level assembly language instruction through disassembly look synchronization method with synchronization method.

{class SynchronizedTest public
    public void the synchronized doSth () {
        System.out.println ( "the Hello World");
    }
    public void doSth1 () {
        the synchronized (SynchronizedTest.class) {
            System.out.println ( "the Hello World");
        }
    }
}
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
the javac SynchronizedTest then decompiled .java see javap -c SynchronizedTest assembler instructions are as follows:

 public synchronized void doSth();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_SYNCHRONIZED //  这是重点 方法锁
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                 
         3: ldc           #3   
         5: invokevirtual #4                 
         8: return

  void doSth1 public ();
    descriptor: () V
    the flags: ACC_PUBLIC
    Code:
      Stack = 2, about locals =. 3, args_size. 1 =
         0: LDC. 5 #                
         2: DUP
         . 3: astore_1
         . 4: // enter the monitorenter synchronization method
         5: getstatic # 2                 
         . 8: LDC. 3 #                 
        10: invokevirtual. 4 #               
        13 is: aload_1
        14: the monitorexit exit normal synchronization method //
        15: GOTO 23 is
        18 is: astore_2
        . 19: aload_1
        20 is: the monitorexit exit // abnormal synchronization method
        21 is: aload_2
        22 is: athrow
        23: return
. 1
2
. 3
. 4
. 5
. 6
. 7
. 8
. 9
10
. 11
12 is
13 is
14
15
16
. 17
18 is
. 19
20 is
21 is
22 is
23 is
24
25
26 is
27
28
29
30
31 is
that we can see the Java bytecode compiler generated for us. In the process for doSth and doSth1 slightly different. That is to say. Different JVM method for processing synchronization and block synchronization code. For synchronization method, JVM ACC_SYNCHRONIZED employed to achieve synchronization marker. For the synchronized block. Using the JVM monitorenter, monitorexit two instructions to achieve synchronization.
ACC_SYNCHRONIZED

The method of synchronizing stage is implicit. There will be a constant pool ACC_SYNCHRONIZED mark synchronization method. When a thread to access a method, it checks whether there ACC_SYNCHRONIZED, if set up, you need to get the monitor lock, and begins execution method, and then release the monitor lock after the method is executed. Then if the other threads to execute the request method, because the monitor can not get a lock to be blocked to live. It is noted that, if during the execution of the method, the occurrence of abnormality, and the internal method does not handle the exception, the monitor lock is automatically released before the exception is thrown out method.
monitorenter with monitorexit

Can be understood as an instruction execution monitorenter lock, execution monitorexit understood to release the lock. Each object maintains a record of the number of times counter is locked. Unlocked object of this counter is 0, when a thread to acquire the lock (execution monitorenter), the counter is incremented to 1, when the lock of the object of obtaining the same thread again, the counter increment again. When the same thread releases the lock (monitorexit instruction execution), the counter is decremented again. When the counter is zero. The lock is released, the other threads can acquire a lock.
Conclusion: The synchronization method and a synchronization code block bottom are achieved by a synchronization monitor.
The difference: the synchronization mode is achieved by a method of the access_flags ACC_SYNCHRONIZED flag is set, the synchronization code block is realized by monitorenter and monitorexit.

monitor resolve

We know that every object is associated with a monitor, and the monitor can be thread owns or release, the Java Virtual Machine (HotSpot) in, monitor by ObjectMonitor achieved its primary data structure is as follows (located HotSpot Virtual Machine Source ObjectMonitor .hpp file, C ++ implementation).

ObjectMonitor () {
    The _count = 0; // number of records
    _recursions = 0; // number of reentrant lock
    _owner = NULL; // point hold ObjectMonitor object thread
    _WaitSet = NULL; // call to the wait, the thread may be added to _WaitSet
    _EntryList = NULL; // wait for a thread to acquire the lock, is added to the list
}
. 1
2
. 3
. 4
. 5
. 6
. 7
Monitor operation is as follows:

For a method for modifying synchronized (block) is:

When multiple threads access the process, then these threads will first be put _EntryList queue, then the thread is blocked state
after a thread obtained when the monitor object, then it can enter the running state, the block performing the method, at this time , _owner ObjectMonitor object points to the current thread, _count plus 1 indicates that the current target is a thread gets the lock.
When the running state is called a thread wait () method, then the current thread releases the monitor object, enters the waiting state, _owner ObjectMonitor object becomes null, _count minus 1, while the thread enters _WaitSet queue until the thread calls notify () method wake up the thread, the thread enters _EntryList queue, re-enter the competition to lock _owner area.
If the current thread is finished, it can also monitor the release of the object, _owner ObjectMonitor object becomes null, _count minus 1.
Since the monitor lock (monitor) is dependent on the underlying operating system Mutex Lock achieved, and needs to be converted from the user mode to kernel mode when switching between threads operating system implementation, the transition between a state requires relatively long time, time cost is relatively high, which is why early synchronized low efficiency reasons. Fortunately, after Java 6 Java JVM-level official from the larger synchronized optimization ultimately improve significantly, Java after 6, in order to obtain and release locks to reduce the consumption of performance caused by the introduction of the concept of lock escalation.

Lock escalation

There are four state synchronized lock, no lock, tend to lock, lock lightweight, heavyweight lock. These states will compete with the state escalated lock can upgrade but can not downgrade, but biased locking state can be reset to the lock-free state.

Biased locking

Because after HotSpot author of a large number of studies have found that most of the time there is no lock contention, often several times to get a thread with a lock, so if every time the competition will increase the number lock is not necessary to pay the price, in order to reduce the cost of acquiring the lock, the lock was introduced bias.
main idea:

If a thread obtains a lock, then the lock to enter bias mode, where Mark Word structure also becomes biased locking structure, when the thread again requesting a lock, and no further synchronization, namely the process of acquiring the lock, so that eliminating the need for a large number of operations concerning the application of locks, which will provide the performance of the program. So, there is no occasion for lock contention, biased locking good optimization results, after all, is likely to be the same repeatedly apply the same thread lock. But the more intense competition for places locks, lock bias on the failure, because this situation is likely to lock a thread for each application are different, and therefore should not be used biased locking In this case, otherwise would be wasted, need to pay attention that tend to lock after the failure, and will not expand immediately heavyweight lock, but the first upgrade to lightweight lock.
Specific process: when a thread blocks and obtain an access code lock object, the lock is recorded in the biased threadID java object header and a stack frame is not active because the biased locking release the lock, so after the thread 1 acquires the lock again when, need to compare the current thread threadID and Java objects header threadID are the same, if the same (or 1 thread acquires the lock objects), you do not need to lock, unlock using CAS; if not (other threads, such as thread 2 to compete lock object rather biased locking storage so it will not take the initiative to release the thread threadID 1), then the need to view the Java thread object recording head 1 is alive, if not survival, then lock the object is reset to the lock-free state, other threads ( thread 2) can be set to compete biased locking; if alive, then immediately find the thread (thread 1) of the stack frame information, if you still need to continue to hold this lock object, then pauses the current thread 1, cancel biased locking, upgrade is a lightweight lock, if thread 1 no longer use the lock object, then the object lock status to lock-free state, re-bias New thread.

Lightweight lock

Lightweight lock is not much considering the competition thread locking object, and the thread that holds the lock time is not long scene. Because the blocking thread needs CPU from user mode to kernel mode, the cost of the larger, if just blocked soon after the lock is released, and that this price is a bit more harm than good, so this time they simply do not block this thread and let it spin this waiting for the lock release.

Principle with the upgrade:
Thread 1 will first target object MarkWord head lock space for storing a copy of the record lock thread 1 stack frame created (called DisplacedMarkWord) acquiring a lightweight lock, then use the CAS replacing the contents of the object header locks the thread storage record (DisplacedMarkWord) address;

If the thread 1 copied object header at the same time (before the thread 1CAS), thread 2 is also prepared to acquire the lock, copy the object header to lock the recording space thread 2, but when the thread 2CAS found the thread 1 has the object header changed, CAS thread 2 fails, then the thread 2 will try to use spin locks to waiting threads 1 to release the lock. Spin lock is simply to let the thread 2 continually trying to get a lock objects in the CAS cycle.

But if you spin too long does not work, because the spin is to consume CPU, so the number of spins is limited, for example, 10 times or 100 times, if the number of times to spin the thread 1 has not released the lock, or thread 1 is still running, still 2 threads spin-wait, so this time it will expand heavyweight lightweight lock lock. In addition heavyweight lock the thread that owns the lock are blocked, preventing the CPU idle.


PS: On this general process locks have a nice WC explain.

Lock elimination

Eliminating the lock is another virtual machine lock optimization, this optimization is more thorough, Java virtual machines running in the context of scanning JIT compiler, the lock can not remove shared resource competition, by eliminating in this way, except there is no the necessary lock, the lock request can save time meaningless, we know that StringBuffer is thread-safe, which contains a lock exists, but if we use StringBuffer inside the function then the code will automatically lock Oh freed after JIT.

Comparison follows:

Advantages Disadvantages lock state Applicable scene
biased locking lock unlock without additional consumption, the difference in time with the asynchronous method nanosecond if competing threads and more, will bring additional locks revocation consumption basically no other thread synchronization competition scene
lightweight lock competing threads will not be blocked but the spin can increase the speed of response if the program has been unable to obtain a small amount of CPU consumption will spin the thread of competition, holds the lock time is not long, the pursuit of response speed
heavyweight lock the thread does not lead to competition from CPU spin thread is blocked with CPU resources consumption, response time is long lock many threads to compete, cut locks held for a long time, the pursuit of throughput when
PS: ReentrantLock underlying implementation is dependent on special CPU instructions, such as sending commands lock and unlock instructions, users do not need switching mode and kernel mode, the efficiency is high (where the underlying principles of the volatile and similar), and synchronized by the monitor lock bottom (monitor) is dependent on the underlying operating system Mutex lock need to switch user mode and kernel mode, the efficiency of It will be lower.

Lock escalation flow chart

The last upgrade offer lock to enlarge unbelievableme drawn:


reference

In-depth understanding of synchronized
Ali expert detached blog
----------------

Original link: https: //blog.csdn.net/qq_31821675/java/article/details/105298334
Copyright: Bloggers 'SoWhat1412' original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.

https://jlwz.cn/userinfo-1000-443397.html
https://jlwz.cn/bbs/userinfo.aspx?touserid=40732&backurl=
https://jlwz.cn/userinfo-1000-443398.html
https://jlwz.cn/userinfo-1000-443401.html
https://jlwz.cn/userinfo-1000-443405.html
https://www.iyamusic.com/user/143753
https://www.iyamusic.com/user/143807
https://www.iyamusic.com/user/143809
https://www.iyamusic.com/user/143812
https://www.iyamusic.com/user/143815
http://www.92kk.com/m/zf7652051/
http://www.92kk.com/m/zf7652051a/
http://www.92kk.com/m/zxcfghrnb
http://www.92kk.com/m/hgffrt4rw
http://www.92kk.com/m/sgsdfhkf
https://streetvoice.cn/zf7652051/
https://streetvoice.cn/zcasdgadas/
https://streetvoice.cn/fdsgffghgxc/
https://streetvoice.cn/nvcbdh/
https://streetvoice.cn/fhvxdm/

Guess you like

Origin www.cnblogs.com/dasdfdfecvcx/p/12633659.html