In our practical application, we may often encounter a scenario where multiple threads read or write the same data, access the same files, and so on. If we do not control this situation, it is very easy to lead to errors. In Java, in order to solve this problem, the concept of critical area is introduced. The so-called critical section refers to a program fragment that accesses a shared resource, which cannot be accessed by multiple threads at the same time.
The synchronization mechanism is provided in Java in order to implement the critical section. When a thread tries to access a critical section, he will use a synchronization mechanism to see if another thread has entered the critical section. If not, he can enter the critical section, or he will be suspended by the synchronization mechanism, specifying the incoming thread to leave the critical section.
The critical section stipulates that only one process is allowed to enter the critical section at a time, and no other processes are allowed to enter. The rule of dispatch (Baidu Encyclopedia):
1. If there are several processes that require access to an idle critical section, only one process is allowed to enter at a time.
2. At any time, there must be more than one process in the critical area. If a process has entered its own critical section, all other processes attempting to enter the critical section must wait.
3, the process of entering the critical area should be exited within a limited time so that other processes can enter their critical areas in time.
4, if the process can not enter their own critical section, you should give up the CPU, to avoid the process of "busy" phenomenon.
The following describes the use of the Synchronized keyword to implement the synchronization mechanism.
First, synchronized keyword 1.1, introduction
Synchronized, we call the lock, mainly used to give methods, code block lock. When a method or block of code uses synchronized, at most one thread at the same time executes the code. When there are multiple threads accessing the Lock method/code block of the same object, only one thread executes at the same time, and the remaining threads must wait for the current thread to execute before executing the code snippet. However, the remaining threads are able to access the non-locking code blocks in the object.
Synchronized mainly consists of two methods: Synchronized method, synchronized block.
1.2. Synchronized method
Declare the Synchronized method by adding the Synchronized keyword to the method declaration. Such as:
Public synchronized void GetResult ();
The Synchronized method Controls access to class member variables. How does it avoid access control for class member variables? We know that the method uses the Synchronized keyword to indicate that the method has been locked, and that the method must be judged whether any other thread is "exclusive" when it accesses the modification method. Each class instance corresponds to a lock, and each synchronized method must invoke the lock of the class instance of the method to execute, otherwise the owning thread is blocked, and once the method executes, the lock is exclusive until the lock is released when the method returns, and the blocked thread can obtain the lock.
In fact, the synchronized method is flawed, and if we declare a large method as synchronized, it will greatly affect the efficiency. If multiple threads are accessing a synchronized method, only one thread executes the method at the same time, while other threads must wait, but if the method does not use synchronized, all threads can execute it at the same time, reducing the total time of execution. So if we know that a method is not being executed by multiple threads or that there is no problem with resource sharing, then the Synchronized keyword is not required. But if you must use the Synchronized keyword, then we can synchronized the code block to replace the synchronized method.
1.3, synchronized block
The synchronized code block acts the same way as the synchronized method, except that it makes the critical section as short as possible, in other words: it only protects the shared data that is needed, and the remaining long blocks of code leave this operation. The syntax is as follows:
Synchronized (object) { //code to allow access control }
If we need to use the Synchronized keyword in this way, then we have to use an object reference as a parameter, usually this parameter is often used as this.
Synchronized (this) { //Allow access to control code}
For synchronized (this) there are the following understandings:
1. When two concurrent threads access the synchronized (this) synchronization code block in the same object, only one thread can be executed within a single time. The other thread must wait for the current thread to finish executing the block before it can execute the code block.
2. However, when one thread accesses one synchronized (this) of object to synchronize a block of code, another thread can still access the non-synchronized (this) synchronous code block in object.
3. In particular, when a thread accesses one of the synchronized (this) synchronization blocks of object, other threads have access to all other synchronized (this) synchronized code blocks in object that are blocked.
4. The third example also applies to other synchronization code blocks. That is, when a thread accesses a synchronized (this) of object to synchronize a block of code, it obtains the object lock of the objects. As a result, other threads are temporarily blocked from accessing all of the synchronization code portions of the object.
5. The above rules also apply to other object locks
http://freewxy.iteye.com/blog/978159, this blog using an example of the above four points are described in more detail, here is not much elaboration.
http://www.cnblogs.com/GnagWang/archive/2011/02/27/1966606.html this blog on the use of synchronized a very good example (take the key into the room). Here because of the length of the LZ is not much elaborated, the following we have to planing synchronized slightly more advanced things.
1.4. Advanced
There is a "first served" principle in Java multithreading, which means who first grabs the key and who uses it first. We know that in order to avoid the problem of resource competition, Java uses the synchronization mechanism to avoid, while the synchronization mechanism is controlled by using the lock concept. So in Java programs, how does a lock show? Here we need to figure out two concepts:
What is a lock?
What is a lock? In daily life, it is a seal on the door, box, drawer and other objects, to prevent others peeping or stealing, play a protective role. Similarly in Java, Locks act as a protection against objects, and if a thread is exclusive of a resource, other threads do not want to use it. Wait till I run out of it!
In the Java Program Runtime environment, the JVM needs to reconcile the data shared between the two types of threads:
1. Instance variables saved in the heap
2. Class variables that are stored in the method area.
In a Java virtual machine, each object and class is logically associated with a single monitor. For an object, the associated monitor protects an instance variable of the object. For classes, the monitor protects class variables for classes. If an object does not have an instance variable, or if a class has no variables, the associated monitor is not monitored at all.
To achieve the exclusive monitoring capabilities of the monitor, the Java Virtual Machine Associates a lock for each object and class. Represents a privilege that only one thread is allowed to have at any time. A thread accesses an instance variable or class variable without a lock. If a thread acquires a lock, it is not possible for other threads to acquire the same lock until 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 obtains the object, the counter adds 1, each time it is released, the counter is reduced by 1, and when the counter value is 0 o'clock, the lock is completely released.
Java programmers do not need to do their own locking, object locks are used inside the Java Virtual machine. In a Java program, you only need to use the synchronized block or the Synchronized method to flag a monitoring area. The Java Virtual machine locks the object or class automatically each time you enter a monitoring area. (Excerpt from the Java Lock mechanism ).
What's the lock?
Before this question we have to be clear: regardless of whether the Synchronized keyword is added to the method or the object, the lock it obtains is an object . Each object in Java can be used as a lock, which is mainly embodied in the following three aspects:
- For synchronous methods, the lock is the current instance object.
- For synchronous method blocks, the lock is an object configured in synchonized brackets.
- for a static synchronization method, the lock is the class object of the current object.
First, let's look at the following example:
public class Threadtest_01 implements runnable{ @Override public synchronized void Run () {for (int i = 0; I & Lt 5} 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 ();}} }
Partial Run Result:
Thread_2run ... Thread_2run ... Thread_4run ... Thread_4run ... Thread_3run ... Thread_3run ... Thread_3run ... Thread_2run ... Thread_4run ...
The result is a bit different from what we expected (these threads are running around), which is supposed to have a sync effect after the Run method plus the Synchronized keyword, which should be followed by a run method. In the above LZ mentioned that a member method plus the Synchronized keyword, is actually to give the Member method lock, the point is that the member method is located in the object itself as the object lock. But in this case we have a total of 10 new ThreadTest objects, each of which holds the object lock of its own thread object, which must not produce a synchronous effect. So: If you want to synchronize these threads, the object locks held by these threads should be shared and unique!
this time synchronized locked the object? What it locks is the call to this synchronization method object. That is, threadtest this object executes synchronous methods in different threads, it forms mutual exclusion. To achieve the effect of synchronization. so will the above Newthread (new threadtest_01 (), "thread_" + i). Start (); Modify to New Thread (ThreadTest, "thread_" + i). Start (); it's OK.
For synchronous methods, the lock is the current instance object.
The above example is using the Synchronized method, we are looking 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 ();}}
Operation 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 private variable lock of each 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 area in the heap memory, that is, the area where the lock variable is stored in the main function, so the object lock is unique and shared. Thread Synchronization!!
The lock is the string object that synchronized here.
For synchronous method blocks, the lock is an object configured in 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 (); }}
Operation 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 synchronous method and is a static synchronous method, so what is the synchronized lock here? We know that static is detached from the object, and it belongs to the class level. Therefore, the object lock is the class instance of the classes in which the static drop is located. Because in the JVM, all loaded classes have a unique class object, which is the only Threadtest_03.class object in that instance. No matter how many instances of the class we have created, its class instance is still one! So object locks are unique and shared. Thread Synchronization!!
For a static synchronization method, the lock is the class object of the current object.
If a synchronized static function A is defined in a class, and a synchronized instance function B is defined, then the same object of this class, obj, does not constitute synchronization when it accesses A and B two methods in multiple threads, respectively. Because their locks are not the same. The lock of the A method is the object of obj, and the lock of B is the class that obj belongs to.
Upgrade of LocksThere are four types of lock in Java, no lock state, biased to lock state, light-weight lock state and heavy lock state, it will gradually upgrade with the competition situation. Locks can be upgraded but not degraded, which means that a biased lock cannot be downgraded to a biased lock after it has been upgraded to a lightweight lock. This lock escalation strategy is not degraded, and is designed to improve the efficiency of acquiring locks and releasing locks. The following main part is mainly for the blog: talk about concurrency (ii) Java SE1.6 in the Synchronized summary.
Lock spin
We know that when a thread enters the synchronization method/code block, if it finds that the synchronization method/code block is occupied by other now, it waits, enters the blocking state, the process performance is low.
In the event of a lock contention may wait for a thing, the thread can not rush into the blocking state, but wait, see if the lock is released immediately, this is the lock spin. The lock spin can be optimized for threading to some extent.
Biased lock
The bias Lock is primarily in order to solve the performance problem of locking in the absence of competition. in most cases, locking is not only not a multi-threaded competition, but always by the same thread multiple times, in order to let the thread get the lock lower cost and introduce a biased lock. When a thread obtains a lock, the thread is able to lock the object multiple times, but each time such an operation results in some overhead performance due to the CAS (CPU compare-and-swap instruction) operation, in order to reduce this overhead, the lock will be biased towards the first thread to get it. If the lock is not fetched by another thread during the next execution, the thread holding the biased lock will never need to be synchronized again.
When other threads try to compete for a bias lock, the thread that holds the biased lock releases the lock.
Lock expansion
Multiple or multiple calls to a lock with too little granularity to lock and unlock, but not as efficient as a large-grained lock call.
Lightweight lock
Lightweight lock can enhance the program synchronization performance is based on "for most of the lock, the entire synchronization cycle is not competitive", this is an empirical data. A lightweight lock creates a space in the stack frame of the current thread called a lock record to store the current point and state of the lock object. If there is no competition, lightweight locks use CAS operations to avoid the overhead of using mutexes, but if there is a lock race, there is additional CAS operations in addition to the cost of mutexes, so that in competitive situations, lightweight locks are slower than traditional heavyweight locks.
1.5 References1, "Java 7 concurrent Programming Practical Manual"
2. Java synchronized detailed
3. Talk about concurrency (ii) synchronized in Java SE1.6
4. the lock mechanism of Java
5. Lock-free programming and lock optimization in Java
"Java Concurrency Programming practice"-----synchronized