1. synchronized usefulness
When learning of the operating system, we will often hear deadlock, mutex and other terms, we know that this is some limited access to resources in multiple threads caused. Similarly, in java
multi-threaded programming, these threads are often at the same time to access a resource, the resource here we can be specific to a variable, an object, a piece of code blocks, even a class. So how to make these threads to access those resources in accordance with our expectations, we must use the keyword synchronized
to access code snippets to protect resources. Thus, when other tasks or threads that want to access the protected code block, first check whether the lock is available, and if Acquires the lock, then the code until the code is finished, in order to release the lock. During the lock code gets executed this thread protected, any other thread wants to access the code block, all will be blocked until the lock is released. So we can use keyword synchronized
rules with <thinking in java> in this book can be summed up:
If you are writing a variable that may next be read by another thread, or is reading a variable that has been written on another thread, you must use synchronization, and must be read with the same thread monitor lock synchronization.
2. synchronized usage
Now that the synchronized
role of keywords, then the next we learn about synchronized
keywords which resources can be protected and how to act on these resources. Here too, we divided into six kinds of situations.
2.1 two threads simultaneously access an object's synchronized method
Here we see a demo:
package SynchronizedDemo;
import java.util.concurrent.TimeUnit;
public class SameThreadSync implements Runnable{ @Override public void run() { synchronized (this) { try { TimeUnit.MILLISECONDS.sleep(3000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("currentTime: " + System.currentTimeMillis() + " " + Thread.currentThread().getName() + " has finished now"); } } }
package SynchronizedDemo;
public class MainThread { public static void main(String[] args) { SameThreadSync runnable = new SameThreadSync(); Thread thread1 = new Thread(runnable, "Amy thread"); Thread thread2 = new Thread(runnable, "Bob thread"); System.out.println("currentTime: " + System.currentTimeMillis()); thread1.start(); thread2.start(); } }
Then we run it, look at the results:
currentTime: 1547988932743
currentTime: 1547988935744 Amy thread has finished now
currentTime: 1547988938748 Bob thread has finished now
As can be seen, Bob thread is executed, it starts executing the thread Amy. In addition, if we put synchronized(this)
into another way to write the result is the same.
package SynchronizedDemo;
import java.util.concurrent.TimeUnit;
public class SameThreadSync implements Runnable{ @Override public synchronized void run() { try { TimeUnit.MILLISECONDS.sleep(3000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("currentTime: " + System.currentTimeMillis() + " " + Thread.currentThread().getName() + " has finished now"); } }
Because the synchronized
block must be given a synchronization object on it, and the most reasonable way is to use the current object whose method is being invoked: synchronized(this)
So we both lock code format is the same object, that is, the current object. Therefore, according to synchronized
the definition of this keyword, the lock is released only when the current object, and another thread to access the object.
When I removed the synchronization synchronized(this)
time, then run again, the results are as follows:
currentTime: 1547989082259
currentTime: 1547989085265 Amy thread has finished now
currentTime: 1547989085265 Bob thread has finished now
This time, we found Bob
and Amy
almost complete at the same time.
2.2 two threads access a synchronization method of two objects
package SynchronizedDemo;
public class MainThread { public static void main(String[] args) { SameThreadSync runnable = new SameThreadSync(); SameThreadSync runnable2 = new SameThreadSync(); Thread thread1 = new Thread(runnable, "Amy thread"); Thread thread2 = new Thread(runnable2, "Bob thread"); System.out.println("currentTime: " + System.currentTimeMillis()); thread1.start(); thread2.start(); } }
Results are as follows:
currentTime: 1547990419528
currentTime: 1547990422533 Bob thread has finished now
currentTime: 1547990422533 Amy thread has finished now
It found that two threads at the same time almost complete, and the second thread to complete more than the first thread. Because the synchronized
lock is the object that is currently running at a time Amy
and Bob
are running two different objects, it does not appear after a thread waits for another thread releases the lock to perform. Otherwise occur Bob
than Amy
before the end, this is not difficult to understand, when Amy
the thread sleep
when after Amy
a thread goes to sleep, cpu
give Bob
the thread, when Amy
after a thread sleep, cpu
not come and give Amy
, Bob
sleep well, on the first execution of the Bob
threads print statements.
Summary : Lock ordinary method, equivalent to the lock on the object's current call.
2.3 two threads access a static method of synchronized
We modify the class SameThread.java
method, and in class MainThread.java
is still created two different objects.
package SynchronizedDemo;
import java.util.concurrent.TimeUnit;
public class SameThreadSync implements Runnable{ @Override public void run() { method(); } private synchronized static void method() { try { TimeUnit.MILLISECONDS.sleep(3000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("currentTime: " + System.currentTimeMillis() + " " + Thread.currentThread().getName() + " has finished now"); } }
Run the following results:
currentTime: 1547991444723
currentTime: 1547991447729 Amy thread has finished now
currentTime: 1547991450734 Bob thread has finished now
Why this Bob
thread to wait Amy
after the completion of the thread, in order to enforce it? Because this is a static method belonging to a class, so a static method lock, is a lock for this class, so access to this class can only be accessed by a thread at the same time, so Bob
have to wait Amy
after the release of the lock of this class, to access the class.
If we synchronized static
replaced synchronized(SameThread.class)
a look at it?
currentTime: 1547991699001
currentTime: 1547991702005 Amy thread has finished now
currentTime: 1547991705006 Bob thread has finished now
We found the same results.
Summary : Lock to lock the static method is equivalent to the current class.
2.4 Non-simultaneous access synchronization method and a synchronization method
package SynchronizedDemo;
import java.util.concurrent.TimeUnit;
public class SameThreadSync implements Runnable{ @Override public void run() { if (Thread.currentThread().getName().equals("Amy thread")) { method1(); } else if (Thread.currentThread().getName().equals("Bob thread")) { method2(); } } private synchronized void method1() { try { TimeUnit.MILLISECONDS.sleep(3000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("currentTime: " + System.currentTimeMillis() + " " + Thread.currentThread().getName() + " has finished now"); } private void method2() { try { TimeUnit.MILLISECONDS.sleep(3000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("currentTime: " + System.currentTimeMillis() + " " + Thread.currentThread().getName() + " has finished now"); } }
package SynchronizedDemo;
public class MainThread { public static void main(String[] args) { SameThreadSync runnable = new SameThreadSync(); Thread thread1 = new Thread(runnable, "Amy thread"); Thread thread2 = new Thread(runnable, "Bob thread"); System.out.println("currentTime: " + System.currentTimeMillis()); thread1.start(); thread2.start(); } }
Run the following results:
currentTime: 1547992475217
currentTime: 1547992478219 Bob thread has finished now
currentTime: 1547992478219 Amy thread has finished now
Almost two threads simultaneously ended. So, if a member variable of a class, when multiple access methods are written, while the object of this class may be held by multiple threads, then the safest approach is to this member variable is set to private, At the same time all the methods of this variable write access should use the synchronized
keyword protected.
Summary : synchronized
The method does not block another thread with a non-object synchronized
method call in.
Ordinary different synchronization methods to access the same object 2.5
We will in the example above method2()
method also add synchronized
keywords, run a code:
currentTime: 1547992878720
currentTime: 1547992881726 Amy thread has finished now
currentTime: 1547992884730 Bob thread has finished now
The results also demonstrate the protection of a member variable method on a say. If one thread A
to access an object of synchronized
key protection method, the other threads B
must wait for the thread A
after the release of the lock in order to access other synchronized
methods.
2.6 simultaneously access a static synchronized and non-synchronized static method
package SynchronizedDemo;
import java.util.concurrent.TimeUnit;
public class SameThreadSync implements Runnable{ @Override public void run() { if (Thread.currentThread().getName().equals("Amy thread")) { method1(); } else if (Thread.currentThread().getName().equals("Bob thread")) { method2(); } } private synchronized static void method1() { try { TimeUnit.MILLISECONDS.sleep(3000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("currentTime: " + System.currentTimeMillis() + " " + Thread.currentThread().getName() + " has finished now"); } private synchronized void method2() { try { TimeUnit.MILLISECONDS.sleep(3000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("currentTime: " + System.currentTimeMillis() + " " + Thread.currentThread().getName() + " has finished now"); } }
operation result:
currentTime: 1547993122882
currentTime: 1547993125888 Amy thread has finished now
currentTime: 1547993125888 Bob thread has finished now
Both are found almost run simultaneously, and why? Because the method1()
method is a static method, and static methods are class level, we have said above, the lock of a static method, similar synchronized(xx.class)
, indicating that the lock of the object is .class
an object, and method2()
lock this general approach, we equivalent synchronized(this)
, indicating the lock is currently running instance of an object, that is method1()
, and method2()
the lock is not the same object, so the two are not affect each other.
Summary: lock static method, the lock class
object is locked to the conventional method, the object lock is an example of the current class, both not affect each other.
3. synchronized core idea
-
A lock can only be one thread simultaneously acquired, did not get the lock thread must wait
-
Each instance has its own corresponding to a lock, independently of each other between different instances; exception: the lock object is
*.class
as wellsynchronized
a modifiedstatic
method, when the class of all objects share the same lock. -
Whether it is the normal method of execution or completion method throws an exception, will release the lock.
Author: rain ghost town
link: https: //www.jianshu.com/p/bd3ba6b9431a
Source: Jane book
Jane book copyright reserved by the authors, are reproduced in any form, please contact the author to obtain authorization and indicate the source.