Home> Java> javaTutorial> body text

Use of synchronized keyword

(*-*)浩
Release: 2019-09-06 16:02:14
forward
2445 people have browsed it

The synchronized keyword is a synchronization lock commonly used in Java concurrent programming. It is used to lock methods or code blocks. When locking code blocks, it can be synchronized(this){}, synchronized(Object){}, synchronized(class) {}.

Use of synchronized keyword

#The lock will be automatically released when the locked content is executed or an exception is thrown during execution.

If you want to manually release the lock, you need to call the wait() method of the locked object to release the lock and put it in a waiting state, switch to other threads to run, and the notify() method only wakes up the object that has been called. wait() method of other threads, but the lock will not be released, and the selection order is not controlled by the code and is implemented by the virtual machine.

Therefore, the wait(), notify(), and notifyAll() methods of the object can only be used with the synchronized keyword to complete scheduling between threads.

The locked method is equivalent to synchronized(this){all the code of the method as a code block}, as follows:

public synchronized void test() { ... }
Copy after login

Equivalent to

public void test() { synchronized (this) { ... } }
Copy after login

The above example is locked is an object of this class. If a static method is locked, we know that the static method belongs to the class and not to the object. Therefore, the static method modified by synchronized locks all objects of this class, that is, even two Instance objects, as long as they belong to this class, will be locked.

public synchronized static void test() { ... }
Copy after login

Equivalent to

public static void test() { synchronized (所在类.class) { ... } }
Copy after login

Whether it is a lock method or a code block, no matter what the reference object is when locking the code block, it is clear as long as you remember one principle, that is, when the reference object Synchronization locks only work when they are the same, otherwise the locks will not be mutually exclusive and can be executed concurrently.

synchronized(this) indicates that the lock takes effect when the object instances of the current class are the same, synchronized(Object) indicates that the lock takes effect when the Object objects are the same, and synchronized(class) indicates that the lock takes effect when they are all of the same class. kick in.

Give a simple example:

public class TestController { public class Task implements Runnable{ private String str; Task(String str){ this.str=str; } @Override public void run() { synchronized (str) { try { Thread.sleep(3000l); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(str); } } } public static void main(String[] args) throws InterruptedException { TestController testController = new TestController(); Thread thread1 = new Thread(testController.new Task("1")); Thread thread2 = new Thread(testController.new Task("1")); thread1.start(); thread2.start(); } }
Copy after login

In the above code, the reference object str is "1". In java, if the String string passes this.str="1", Assignment is equivalent to str=String.valueOf("1"). If the string "1" has been initialized before, the previous one will be taken directly, so it is the same object. According to the principle introduced above, the lock will take effect, so the result is that 1 will be output after 3 seconds, and 1 will be output after another 3 seconds.

If thread2 is changed to

Thread thread2 = new Thread(testController.new Task("2"));
Copy after login

then one of the reference objects is "1" and the other is "2", which are not the same object, so the lock will not be mutually exclusive, and it will not works, so the result is that 1 and 2 are output almost simultaneously after 3 seconds.

All of the above are multiple threads calling the same method at the same time. What if different methods are called?

public class Test{ public synchronized void m1(){ System.out.println("m1 running..."); try { Thread.sleep(3000l); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("m1 end"); } public synchronized void m2(){ System.out.println("m2 running..."); System.out.println("m2 end"); } public static void main(String[] args) { Test test = new Test(); new Thread(new Runnable() { @Override public void run() { test.m1(); } }).start(); new Thread(new Runnable() { @Override public void run() { test.m2(); } }).start(); } }
Copy after login

The output result of the above code is:

m1 running... //过3秒 m1 end m2 running... m2 end
Copy after login

As mentioned above, the synchronized modification is equivalent to synchronized(this){all the code of the method as a code block}, and this represents is an object, that is to say, the first Thread obtains the lock of the test object. Because the objects are all the same test, the second Thread cannot obtain the lock and is blocked.

Change the above example into the following:

private String str = "1"; public void m1(){ synchronized(str){ System.out.println("m1 running..."); try { Thread.sleep(3000l); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("m1 end"); } } public void m2(){ synchronized(str){ System.out.println("m2 running..."); System.out.println("m2 end"); } }
Copy after login

When the first Thread calls m1(), it obtains the lock of the object str, and the second Thread also needs it when it calls m2(). Obtain the lock of the object str, and because they are the same Test object, the two strs are also the same object, so the second Thread will be blocked because it cannot obtain the lock, and the output result is the same as the previous example.

If the above example is transformed into the following:

public class M1 { public void m(String str){ synchronized (str) { System.out.println("m1 runing"); try { Thread.sleep(3000l); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("m1 end"); } } } public class M2 { public void m(String str){ synchronized (str) { System.out.println("m2 runing"); System.out.println("m2 end"); } } } public class Test { public static void main(String[] args) { String str = "1"; new Thread(new Runnable() { @Override public void run() { new M1().m(str); } }).start(); new Thread(new Runnable() { @Override public void run() { new M2().m(str); } }).start(); } }
Copy after login

The method called this time is in two classes, but the result is the same as the previous two examples, because the locked They are all str objects passed in. There is only one lock for the same object. If the first Thread takes it, the second Thread can only wait.

Summary:

A. Regardless of whether the synchronized keyword is added to a method or an object, if the object it acts on is non-static, the lock it acquires is the object ; If the object synchronized acts on is a static method or a class, the lock it acquires is for the class, and all objects of the class have the same lock.

B. Each object has only one lock associated with it. Whoever gets this lock can run the code it controls.

C. Achieving synchronization requires a lot of system overhead and may even cause deadlock, so try to avoid unnecessary synchronization control

The above is the detailed content of Use of synchronized keyword. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:csdn.net
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!