[Java concurrent programming practice] -- synchronized, asynchronous ynchronized
In our practical application, we may often encounter such a scenario: multiple threads read or write the same data, access the same file, and so on. If we do not control this situation, it is very easy to cause errors. In java, the concept of critical section is introduced to solve this problem. The so-calledA critical section refers to a program segment that accesses shared resources. These shared resources cannot be accessed by multiple threads at the same time.
In java, a synchronization mechanism is provided to implement the critical section. When a thread tries to access a critical section, it uses a synchronization mechanism to check whether other threads have entered the critical section. If no thread exists, it can enter the critical section. Otherwise, it will be suspended by the synchronization mechanism and the specified thread will leave the critical section.
The critical section stipulates that only one process is allowed to enter the critical section at a time. Other processes are not allowed to enter the critical section after entry. The scheduling rule is (Baidu encyclopedia ):
1. If several processes require entering the idle critical section, only one process is allowed at a time.
2. At any time, there cannot be more than one process in the critical section. If a process has entered its own critical section, all other processes that attempt to enter the critical section must wait.
3. Processes entering the critical section should exit within a limited period of time so that other processes can enter their critical section in time.
4. If a process cannot enter its critical section, the CPU should be used out to avoid the process being "busy.
The following describes how to use the synchronized keyword to implement synchronization.
1. synchronized keyword 1.1. Introduction
Synchronized, the lock we call it, is mainly used to lock methods and code blocks. When synchronized is used for a method or code block, at most one thread is executing the code segment at the same time. When multiple threads access the lock method/code block of the same object, only one thread is executing at a time. Other threads must wait until the current thread finishes executing the code segment. However, other threads can access non-lock code blocks in the object.
Synchronized mainly includes two methods: synchronized Method and synchronized block.
1.2. synchronized Method
The synchronized method is declared by adding the synchronized keyword to the method declaration. For example:
public synchronized void getResult();
The synchronized method controls access to class member variables. How does it avoid access control of class member variables? We know that the method uses the synchronized keyword to indicate that the method has been locked. When any thread accesses the method, it must determine whether other threads of the method are "exclusive ". Each class instance corresponds to a lock, and each synchronized method must call the lock of the class instance of this method before execution. Otherwise, the corresponding thread is blocked, and once the method is executed, the lock is exclusive, the lock is released only when the method is returned. The blocked thread can obtain the lock.
In fact, the synchronized method is flawed. If we declare a large method as synchronized, the efficiency will be greatly affected. If multiple threads are accessing a synchronized method, only one thread is executing the method at the same time, and other threads must wait. However, if the method does not use synchronized, all threads can execute it at the same time, reducing the total execution time. Therefore, if we know that a method will not be executed by multiple threads or that there is no resource sharing problem, we do not need to use the synchronized keyword. However, if you must use the synchronized keyword, we can replace the synchronized method with the synchronized code block.
1.3. synchronized Block
The synchronized code block plays the same role as the synchronized method, but it makes the critical section as short as possible. In other words, it only protects the required shared data, this operation is available for other long code blocks. Syntax:
Synchronized (object) {// code that allows access control}
If we need to use the synchronized keyword in this way, we must use an object reference as a parameter. this parameter is usually used as this.
Synchronized (this) {// code that allows access control}
You can understand synchronized (this) as follows:
1. When two concurrent threads access the synchronized (this) synchronization code block of the same object, only one thread can be executed within a time period. The other thread must wait until the current thread finishes executing this code block before executing this code block.
2. However, when one thread accesses a synchronized (this) synchronization code block of the object, the other thread can still access the non-synchronized (this) synchronization code block of the object.
3. In particular, when a thread accesses a synchronized (this) synchronization code block of the object, other threads operate on all other synchronized (this) access to the synchronization code block will be blocked.
4. The third example also applies to other synchronous code blocks. That is to say, when a thread accesses a synchronized (this) synchronization code block of an object, it obtains the object lock of this object. As a result, access by other threads to all the synchronized code parts of the object will be temporarily blocked.
5. The above rules apply to other Object locks.
Bytes.
(Take the key into the room ). Here, due to space issues, LZ will not elaborate much. Next we will plan something about synchronized a little advanced.
1.4. Advanced
In java multithreading, there is a "come first" principle, that is to say, Who grabs the key first and who uses it first. We know that java uses synchronous mechanism to avoid resource competition issues, while synchronization mechanism is controlled by the lock concept. How is the lock embodied in Java programs? Here we need to clarify two concepts:
What is a lock?
What is a lock? In daily life, it is a plug-in for objects such as doors, boxes, and drawers, to prevent others from peeking or stealing. Similarly, in java, the lock protects the object. If a thread excludes a certain resource, do not use other threads? Wait until I finish it!
In the java program running environment, the JVM must coordinate the data shared by the two types of threads:
1. instance variables stored in the heap
2. class variables saved in the method area.
In a Java virtual machine, each object and class are logically associated with a monitor. For objects, the associated monitor protects the instance variables of objects. For a class, the class variable of the monitor protection class. If an object has no instance variables, or a class has no variables, the associated monitor will not monitor anything.
To achieve the exclusive monitoring capability of the monitor, the Java Virtual Machine associates a lock with each object and class. Indicates that only one thread is allowed at any time. The thread does not need to lock instance variables or class variables. If a thread acquires a lock, other threads cannot obtain the same lock before it releases the lock. A thread can lock the same object multiple times. For each object, the Java Virtual Machine maintains a lock counter. Each time the thread acquires this object, the counter is incremented by 1. Each time the counter is released, the counter is reduced by 1. When the counter value is 0, the lock is completely released.
Java programmers do not need to lock themselves. The object lock is used inside the java Virtual Machine. In java programs, you only need to use the synchronized block or the synchronized Method to mark a monitoring area. Every time you enter a monitoring area, the java Virtual Machine automatically locks the object or class. (From the lock mechanism of java ).
What is the lock?
Before this problem, we must make it clear that no matter whether the synchronized keyword is added to a method or an object, the lock it acquires is an object. Every object in java can be used as a lock. It is mainly reflected in the following three aspects:
For the synchronization method, the lock is the current instance object.
For synchronous method blocks, the lock is the object configured in the Synchonized brackets.
For static synchronization methods, the lock is the Class Object of the current object.First, let's take a look at the following example:
public class ThreadTest_01 implements Runnable{ @Override public synchronized void run() { for(int i = 0 ; i < 3 ; i++){ System.out.println(Thread.currentThread().getName() + "run......"); } } public static void main(String[] args) { for(int i = 0 ; i < 5 ; i++){ new Thread(new ThreadTest_01(),"Thread_" + i).start(); } }}
Some running results:
Thread_2run......Thread_2run......Thread_4run......Thread_4run......Thread_3run......Thread_3run......Thread_3run......Thread_2run......Thread_4run......
This result is a little different from our expected results (these threads are running in disorder here). It is reasonable to say that after the run method is added with the synchronized keyword, the synchronization effect will be generated, these threads should execute the run method one by one. As mentioned above, after adding the synchronized keyword to a member method, LZ actually adds a lock to the member method. The specific point is to use the object of the member method as the object lock. However, in this instance, we have a total of 10 new ThreadTest objects. Each thread will hold the object lock of its own thread object, which must not produce synchronization results. Therefore:If you want to synchronize these threads, the Object locks held by these threads should be shared and unique!
Which object is synchronized locked at this time? The lock is to call the synchronization method object. That is to say, when the threadTest object executes the synchronization method in different threads, it will form a mutex. To achieve the synchronization effect.Therefore, add the new Thread (new ThreadTest_01 (), "Thread _" + I) above ). start (); change to new Thread (threadTest, "Thread _" + I ). start.
For the synchronization method, the lock is the current instance object.
The above example uses the synchronized method. Let's look at the synchronized code block:
public class ThreadTest_02 extends Thread{ private String lock ; private String name; public ThreadTest_02(String name,String lock){ this.name = name; this.lock = lock; } @Override public void run() { synchronized (lock) { for(int i = 0 ; i < 3 ; i++){ System.out.println(name + " run......"); } } } public static void main(String[] args) { String lock = new String("test"); for(int i = 0 ; i < 5 ; i++){ new ThreadTest_02("ThreadTest_" + i,lock).start(); } }}
Running result:
ThreadTest_0 run......ThreadTest_0 run......ThreadTest_0 run......ThreadTest_1 run......ThreadTest_1 run......ThreadTest_1 run......ThreadTest_4 run......ThreadTest_4 run......ThreadTest_4 run......ThreadTest_3 run......ThreadTest_3 run......ThreadTest_3 run......ThreadTest_2 run......ThreadTest_2 run......ThreadTest_2 run......
In the main method, we create a String object lock and assign this object to the lock private variable of every ThreadTest2 thread object. We know that there is a string pool in java, so the lock private variables of these threads actually point to the same region in the heap memory, that is, the region where the lock variable in the main function is stored, therefore, the object lock is unique and shared. Thread Synchronization !!
Synchronized locks the String object.
For synchronous method blocks, the lock is the object configured in the Synchonized brackets.
public class ThreadTest_03 extends Thread{ public synchronized static void test(){ for(int i = 0 ; i < 3 ; i++){ System.out.println(Thread.currentThread().getName() + " run......"); } } @Override public void run() { test(); } public static void main(String[] args) { for(int i = 0 ; i < 5 ; i++){ new ThreadTest_03().start(); } }}
Running result:
Thread-0 run......Thread-0 run......Thread-0 run......Thread-4 run......Thread-4 run......Thread-4 run......Thread-1 run......Thread-1 run......Thread-1 run......Thread-2 run......Thread-2 run......Thread-2 run......Thread-3 run......Thread-3 run......Thread-3 run......
In this example, the run method uses a synchronization method and a static synchronization method. What is the synchronized lock here? We know that static excludes objects and belongs to the class level. Therefore, the object lock is the Class instance of the Class where the static release is located. In JVM, all loaded classes have unique class objects, which are the only ThreadTest_03.class objects in this instance. No matter how many instances of this class are created, its class instance is still one! Therefore, the object lock is unique and shared. Thread Synchronization !!
For static synchronization methods, the lock is the Class Object of the current object.
If A class defines the static function A of synchronized and also defines the instance function B of synchronized, the same object of this class is Obj, when two Methods A and B are accessed in multiple threads, synchronization is not formed because their locks are different. The lock of method A is the object Obj, and the lock of Method B is the Class to which Obj belongs.
Lock upgradeThere are four locks in java, which are unlocked, tend to be locked, lightweight, and heavyweight locks. They will gradually upgrade with the competition. The locks can be upgraded but cannot be downgraded. This means that the loose lock cannot be downgraded to a loose lock after being upgraded to a lightweight lock. This lock upgrade policy cannot be downgraded to improve the efficiency of obtaining and Releasing locks. The following is a summary of Synchronized in Java SE1.6.
Lock spin
We know that when a thread enters the synchronous method/code block, if it finds that the synchronous method/code block is occupied by others, it will wait and enter the blocking state, the performance of this process is low.
In the event of lock contention, the thread may not be so anxious to enter the blocking state, but wait and see if the lock is released immediately. This is the lock spin. To some extent, the lock spin can optimize the thread.
Biased lock
The biased lock mainly aims to solve the performance problem of the lock without competition.In most cases, the lock not only does not have multi-thread competition, but is always obtained multiple times by the same thread. In order to make the thread get the lock at a lower cost, a biased lock is introduced. When a thread acquires a lock, the thread can lock the object multiple times, but every time such an operation is executed, the CAS (CPU Compare-And-Swap command) operation causes some overhead to consume performance. To reduce this overhead, this lock will be biased towards the first thread to obtain it, if the lock is not obtained by other threads, the thread holding the biased lock will never need to be synchronized.
When other threads attempt to compete for locking, the thread holding the locking will release the lock.
Lock Expansion
The consumption of locking and unlocking is not as efficient as a large-granularity lock call.
Lightweight lock
The lightweight lock can improve the synchronization performance of the program based on "there is no competition for the vast majority of locks throughout the synchronization cycle", which is an empirical data. The lightweight lock creates a space named lock record in the stack frame of the current thread to store the current direction and status of the lock object. If no competition exists, the CAS operation is used for lightweight locks to avoid the overhead of mutex. However, in addition to the overhead of mutex, CAS operations are also performed, therefore, in the case of competition, lightweight locks will be slower than traditional heavyweight locks.
1.5 references1. Java 7 concurrency Programming Practice Manual
2. java synchronized
3. Talk about concurrency (2) Synchronized in Java SE1.6
4. java Lock Mechanism
5. Java lock-free programming and lock Optimization
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.