Java Concurrency Programming: synchronized
Although multi-threading programming greatly improves efficiency, it also poses some pitfalls. For example, two threads that insert non-duplicated data into a database table can cause the same data to be inserted in the database. Today we come together to discuss thread safety issues and what mechanisms are available in Java to address threading security issues.
The following is the directory outline for this article:
I. When will a thread safety issue occur?
Two. How do I troubleshoot thread safety issues?
Three. Synchronized synchronous method or synchronization block
If there is any difference, please understand and welcome the criticism.
Please respect the author's labor results, reproduced please indicate the original link:
Http://www.cnblogs.com/dolphin0520/p/3920370.html
I. When will a thread safety issue occur?
There is no thread-safety problem in a single thread, and in multithreaded programming, it is possible to have simultaneous access to the same resource, which can be a resource of various types: A variable, an object, a file, a database table, and so on, and when multiple threads access the same resource at the same time, There is a problem:
Because the process performed by each thread is not controllable, it is likely that the final result will be contrary to the actual desire or directly cause a program error.
To give a simple example:
There are now two threads that read data from the network, and then insert a database table that requires that duplicate data not be inserted.
Then there must be two operations in the process of inserting the data:
1) Check the database for the existence of the data;
2) is not inserted if it exists, or inserted into the database if it does not exist.
This can happen if two threads are represented by thread-1 and Thread-2, and thread-1 and thread-2 all read the data x at some point:
Thread-1 to check the database for data x, and then thread-2 to check the database for the presence of data X.
As a result, the results of the two thread checks are that there is no data x in the database, and two threads are inserting data x into the database table respectively.
This is a thread-safe issue where multiple threads accessing a resource at the same time cause the program to run without the results that you want to see.
In this, this resource is called a critical resource (also known as a shared resource).
That is, when multiple threads access critical resources at the same time (an object, a property in an object, a file, a database, and so on), a thread-safety issue can occur.
However, when multiple threads execute a method, local variables inside the method are not critical resources because the method is executed on the stack, and the Java stack is thread-private, so there is no thread-safety issue.
Two. How do I troubleshoot thread safety issues?
So in general, how to solve the problem of thread safety?
Basically, all concurrency patterns use the "serialized access critical resource" scenario when addressing thread-safety issues, that is, at the same time, only one thread can access the critical resource, also known as synchronous mutex access.
Typically, a lock is prepended to the code that accesses the critical resource, and the lock is released when the critical resource is accessed, allowing other threads to continue to access it.
In Java, there are two ways to achieve synchronous mutex access: synchronized and lock.
This article mainly describes the use of synchronized, lock using the method described in the next blog post.
Three. Synchronized synchronous method or synchronization block
Before we know how to use the Synchronized keyword, let's take a look at a concept: a mutex, as the name implies: a lock that can reach the purpose of exclusive access.
As a simple example: if you add a mutex to a critical resource, when a thread accesses that critical resource, the other threads can only wait.
In Java, each object has a lock tag (monitor), also known as a monitor, when multiple threads access an object at the same time, the thread only acquires the lock on that object to access it.
In Java, you can use the Synchronized keyword to mark a method or block of code, and when a thread invokes the object's synchronized method or accesses a synchronized code block, the thread obtains the lock on that object. Other threads are temporarily unable to access this method, and the thread will not release the lock on the object until the method is executed or the code block is executed, and other threads can execute the method or block of code.
Here are a few simple examples to illustrate the use of the Synchronized keyword:
1.synchronized method
In the following code, two threads each invoke the InsertData object to insert the data:
public class Test {public static void Main (string[] args) { final insertdata insertdata = new InsertData ();
new Thread () {public void run () { Insertdata.insert (Thread.CurrentThread ());} ; }. Start (); New Thread () {public void run () { Insertdata.insert (Thread.CurrentThread ());} ; }. Start (); } } Class InsertData {private arraylist<integer> ArrayList = new arraylist<integer> ();p ublic void Insert (Thread Thread) {for (int i=0;i<5;i++) {System.out.println (Thread.getname () + "inserting data" +i); Arraylist.add (i);}}}
At this point the output of the program is:
Description Two threads executing the Insert method at the same time.
If you precede the Insert method with the keyword synchronized, the result is:
Class InsertData {private arraylist<integer> ArrayList = new arraylist<integer> ();p ublic synchronized void Insert (thread thread) {for (int i=0;i<5;i++) {System.out.println (Thread.getname () + "inserting data" +i); Arraylist.add (i);}}
The output from the above shows that the Thread-1 insert data is Thread-0 after the data has been inserted. Description Thread-0 and Thread-1 are sequential execution of the Insert method.
This is the synchronized method.
However, there are a few points to note:
1) When a thread is accessing an object's Synchronized method, other threads cannot access the object's other synchronized methods. The reason is simple because an object has only one lock, and when a thread acquires the lock on the object, the other thread cannot get the lock on the object, so the other synchronized methods of the object cannot be accessed.
2) When a thread is accessing an object's Synchronized method, other threads can access the object's non-synchronized method. The reason is simple, access to the non-synchronized method does not need to obtain the lock of the object, if a method does not use the Synchronized keyword decoration, it is not used to critical resources, then other threads can access this method,
3) If a thread a needs to access the Synchronized method Fun1 of the object Object1, another thread B needs to access the Synchronized method Fun1 of the object object2, even if Object1 and Object2 are the same type), There is no thread-safety problem because they are accessing different objects, so there is no mutex problem.
2.synchronized code block
The synchronized code block resembles the following form:
Synchronized (synobject) {}
When this block of code is executed in a thread, the thread acquires the lock of the object Synobject, which makes it impossible for other threads to access the code block at the same time.
The synobject can be this, which represents the lock that gets the current object, or it can be a property in the class that represents the lock that gets the property.
For example, the Insert method above can be changed to the following two kinds of forms:
Class InsertData {private arraylist<integer> ArrayList = new arraylist<integer> ();p ublic void Insert (Thread Thread) {synchronized (this) {for (int i=0;i<100;i++) {System.out.println (Thread.getname () + "inserting data" +i); Arraylist.add (i);}}}
Class InsertData {private arraylist<integer> ArrayList = new arraylist<integer> ();p rivate Object object = new Object ();p ublic void Insert (thread thread) {synchronized (object) {for (int i=0;i<100;i++) {System.out.println ( Thread.getname () + "in insert Data" +i); Arraylist.add (i);}}}
As can be seen from the above, synchronized code blocks are much more flexible to use than the Synchronized method. Because it is possible that only a subset of the code in a method needs to be synchronized, if the whole method is synchronized with synchronized at this time, the program execution efficiency will be affected. This problem can be avoided with the use of synchronized blocks of code, and synchronized blocks can be synchronized only where they need to be synchronized.
In addition, each class also has a lock that can be used to control concurrent access to static data members.
And if one thread executes a non-static synchronized method of an object, another thread needs to execute the static synchronized method of the class to which the object belongs, and no mutex occurs because access to the static The synchronized method takes a class lock, and accessing a non-static synchronized method consumes an object lock, so there is no mutex.
Look at the following code to understand:
public class Test {public static void Main (string[] args) { final insertdata insertdata = new InsertData ();
new Thread () { @Override public void Run () { insertdata.insert (); } }. Start (); New Thread () { @Override public void Run () { insertdata.insert1 (); } }. Start (); } } Class InsertData {public synchronized void Insert () {System.out.println ("execute Insert"); try {thread.sleep ()} catch ( Interruptedexception e) {e.printstacktrace ();} System.out.println ("Execute insert Complete");} Public synchronized static void Insert1 () {System.out.println ("execution Insert1"); System.out.println ("Execution insert1 Complete");}}
implementation results;
The first thread executes the Insert method and does not cause the second thread to execute the Insert1 method blocking behavior.
Let's take a look at what the Synchronized keyword really does, and we'll decompile its bytecode to see what the following code will do to decompile the bytecode:
public class InsertData {Private Object object = New Object ();p ublic void Insert (thread thread) {synchronized (Object) {}}p ublic synchronized void Insert1 (thread thread) {}public void Insert2 (thread thread) {}}
The bytecode obtained from the anti-compilation can be seen, synchronized code block actually more than the Monitorenter and monitorexit two instructions. When the monitorenter instruction executes, the lock count of the object is added to 1, while the monitorexit instruction will reduce the lock count of the object by 1, which is similar to the PV operation inside the operating system, and the PV operation inside the operating system is used to control the access of multiple threads to critical resources.
One thing to note: for synchronized methods or synchronized blocks of code, when an exception occurs, the JVM automatically frees the lock occupied by the current thread, and therefore does not cause a deadlock due to an exception.
Resources:
The idea of Java programming
http://ifeve.com/synchronized-blocks/
http://ifeve.com/java-synchronized/
http://blog.csdn.net/ns_code/article/details/17199201