This article describes the difference between Synchronized (object lock) and Static Synchronized (class lock) in Java. Share it for your reference, as follows:
The difference between Synchronized and Static Synchronized
By analyzing the analysis of these two usages, we can understand the concept of lock in java. One is an instance lock (locked on an instance object. If the class is a singleton, then the lock also has the concept of a global lock), and the other is a global lock (the lock is targeted at a class. No matter how many objects the instance is, the threads share the lock). The instance lock corresponds to the synchronized keyword, while the class lock (global lock) corresponds to the static synchronized (or locked on the class or classloader object of the class).
The following article gives a good summary:
1. The difference between synchronized and static synchronized
synchronized locks the current instance (current object) of the class to prevent other threads from accessing all synchronized blocks of the instance of the class at the same time. Note that this is the "current instance of the class". There is no such constraint on two different instances of the class.
Then static synchronized happens to control the concurrent access of all instances of the class, and static synchronized restricts all instances of the class in multi-threads to access the code block corresponding to the class in jvm at the same time. In fact, if there is synchronized in a method or a code block in a class, after generating an instance of the class, the instance will also have a monitoring block to prevent threads from concurrently accessing the synchronized protection block of the instance. Static synchronized is a monitoring block common to all instances of the class. This is the difference between the two of them. In other words, synchronized is equivalent to this.synchronized, while static synchronized is equivalent to Something.synchronized. (Addressed later)
A Japanese author, Jie Chenghao's "Java Multithreaded Design Pattern" has a column like this:
pulbic class Something(){ public synchronized void isSyncA(){} public synchronized void isSyncB(){} public static synchronized void cSyncA(){} public static synchronized void cSyncB(){} }So, if there are two instances x and y of Something class, what is the case when the following group of methods are accessed simultaneously by multiple threads?
axisSyncA() and x.isSyncB()
bxisSyncA() and y.isSyncA()
cxcSyncA() and y.cSyncB()
dxisSyncA() and Something.cSyncA()
Here, it is clear that it can be judged:
a, are all synchronized domain accesses to the same instance (x), and therefore cannot be accessed simultaneously. (Different synchronized domains that access x in multithreads cannot be accessed simultaneously)
If x.isSyncA() is accessed in multiple threads, because it is still the same instance and locked on the same method, it cannot be accessed in multiple threads at the same time. (The same synchronized domain that accesses x in multithreads cannot be accessed at the same time)
b, is for different instances, so it can be accessed at the same time (object locks have no lock constraints for different object instances)
c, because it is static synchronized, different instances will still be restricted, which is equivalent to Something.isSyncA() and Something.isSyncB(), so it cannot be accessed at the same time.
So, what about d?, the answer in the book can be accessed simultaneously. The reason for the answer is that synchronzied is that the instance method and synchronzied class method are different from the lock.
Personal analysis means that synchronized and static synchronized are equivalent to two gangs, each of which has its own control, and there is no constraint on each other and can be accessed at the same time.
For example:
public class TestSynchronized { public synchronized void test1() { int i = 5; while( i-- > 0) { System.out.println(Thread.currentThread().getName() + " : " + i); try { Thread.sleep(500); } catch (InterruptedException ie) { } } } public static synchronized void test2() { int i = 5; while( i-- > 0) { System.out.println(Thread.currentThread().getName() + " : " + i); try { Thread.sleep(500); } catch (InterruptedException ie) { } } } public static void main(String[] args) { final TestSynchronized myt2 = new TestSynchronized(); Thread test1 = new Thread( new Runnable() { public void run() { myt2.test1(); } }, "test1" ); Thread test2 = new Thread( new Runnable() { public void run() { TestSynchronized.test2(); } }, "test2" ); test1.start(); test2.start(); // TestRunnable tr=new TestRunnable(); // Thread test3=new Thread(tr); // test3.start(); } }test1 : 4 test2 : 4 test1 : 3 test2 : 3 test2 : 2 test1 : 2 test2 : 1 test1 : 1 test1 : 0 test2 : 0
The above code synchronized modifies the static method and the instance method at the same time, but the running results are alternately performed, which proves that class locks and object locks are two different locks, controlling different regions, and they do not interfere with each other. Similarly, while threads obtain object locks, they can also obtain this type of lock, that is, they obtain two locks at the same time, which is allowed.
in conclusion:
A: synchronized static is the scope of a certain class. synchronized static cSync{} prevents multiple instances in multiple threads from accessing the synchronized static method in this class at the same time. It works on all object instances of a class.
B: synchronized is the scope of an instance. synchronized isSync(){} prevents this instance from accessing the synchronized method of this class at the same time.
In fact, it is very simple to summarize.
2. The difference between synchronized method and synchronized code fast
There is no difference between synchronized methods(){} and synchronized (this){}, but synchronized methods(){} is convenient for reading comprehension, while synchronized (this){} can more accurately control conflict restrict access areas, and sometimes perform more efficiently.
Comparison of efficiency between two methods:
1. Synchronize the block, the code is as follows:
import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TestSynchronized { /** * @param args */ public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final CountDownLatch cdOrder = new CountDownLatch(1); final CountDownLatch cdAnswer = new CountDownLatch(3); final SynchonizedClass sc = new SynchonizedClass(); for(int i=0; i<3; i++){ Runnable runnable = new Runnable(){ public void run() { try{ cdOrder.await(); sc.start(); cdAnswer.countDown(); } catch(Exception e){ e.printStackTrace(); } } }; service.execute(runnable); } try{ Thread.sleep((long) (Math.random()*10000)); System.out.println("Thread" + Thread.currentThread().getName() + "Publish execution command"); cdOrder.countDown(); long beginTime = System.currentTimeMillis(); System.out.println("Thread" + Thread.currentThread().getName() + "The command has been sent, waiting for the result"); cdAnswer.await(); System.out.println("Thread" + Thread.currentThread().getName()) + "All response results have been received, the time taken is: " + (System.currentTimeMillis()-beginTime)); }catch(Exception e){ e.printStackTrace(); } service.shutdown(); } } class SynchonizedClass{ public void start() throws InterruptedException{ Thread.sleep(100);//Execute other logic to consume time synchronized(this){ System.out.println("I ran it with 10 ms"); } } } The operation results are as follows:
Thread main releases the execution command, the thread main has sent the command, waiting for the result I ran and used 10 ms
I've run using 10 ms
I've run using 10 ms
The thread main has received all response results, and the time taken is: 110
The synchronization method, the code is as follows:
import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TestSynchronized { /** * @param args */ public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final CountDownLatch cdOrder = new CountDownLatch(1); final CountDownLatch cdAnswer = new CountDownLatch(3); final SynchonizedClass sc = new SynchonizedClass(); for(int i=0; i<3; i++){ Runnable runnable = new Runnable(){ public void run() { try{ cdOrder.await(); sc.start(); cdAnswer.countDown(); } catch(Exception e){ e.printStackTrace(); } } }; service.execute(runnable); } try{ Thread.sleep((long) (Math.random()*10000)); System.out.println("Thread" + Thread.currentThread().getName() + "Publish execution command"); cdOrder.countDown(); long beginTime = System.currentTimeMillis(); System.out.println("Thread" + Thread.currentThread().getName() + "The command has been sent, waiting for the result"); cdAnswer.await(); System.out.println("Thread" + Thread.currentThread().getName()) + "All response results have been received, the time taken is: " + (System.currentTimeMillis()-beginTime)); }catch(Exception e){ e.printStackTrace(); } service.shutdown(); } } class SynchonizedClass{ public synchronized void start() throws InterruptedException{ Thread.sleep(100);// Execute other logic time // synchronized(this){ System.out.println("I used 10 ms"); // } } }The operation results are as follows:
Thread main releases the execution command, the thread main has sent the command, waiting for the result I ran and used 10 ms
I've run using 10 ms
I've run using 10 ms
The thread main has received all response results, and the time taken is: 332
The difference between the two is: 222ms.
Comparison shows that synchronous code blocks are more efficient than synchronization methods.
Supplementary memory:
1. There are two scopes of synchronized keywords:
1) It is within an object instance. Synchronized aMethod(){} can prevent multiple threads from accessing the synchronized method of this object at the same time (if an object has multiple synchronized methods, as long as one thread accesses one of the synchronized methods, other threads cannot access any synchronized methods in the object at the same time). At this time, the synchronized method of different object instances is uninterrupted. That is to say, other threads can still access the synchronized method in another object instance of the same class at the same time;
2) It is the scope of a certain class. Synchronized static aStaticMethod{} prevents different instance objects (or the same instance object) in multiple threads from accessing the synchronized static method in this class at the same time. It works on all object instances of a class.
2. In addition to using the synchronized keyword before the method, the synchronized keyword can also be used in a block in the method, indicating that only mutually exclusive access is performed on the resources of this block. The usage is: synchronized(this){/*block*/} (or synchronized(obj){/*block*/}), and its scope is the current object;
3. The synchronized keyword cannot be inherited. That is to say, the method of the base class synchronized f(){} is not automatically synchronized f(){} in the inherited class, but becomes f(){}. The inheritance class requires you to explicitly specify that one of its methods is synchronized;
Some understanding of synchronized(this) (explain the object lock well, pay attention to the this keyword in it)
1. When two concurrent threads access this synchronized(this) synchronized code block in the same object object, only one thread can be executed within one time. Another thread must wait for the current thread to execute this code block before it can execute the code block.
2. However, when one thread accesses a synchronized (this) synchronization code block of an object, another thread can still access the non-synchronized (this) synchronization code block in that object.
3. It is particularly critical that when a thread accesses a synchronized (this) synchronization code block of an object, other threads will block access to all other synchronized (this) synchronization code blocks in the object.
4. The third example also applies to other synchronous code blocks. That is, when a thread accesses a synchronized(this) synchronization code block of an object, it obtains the object lock of this object. As a result, other threads access to all synchronous code parts of the object object is temporarily blocked.
5. The above rules also apply to other object locks.
Add a piece of code to facilitate testing of synchronized keywords (simple modification)
public class TestSynchronized { public void test1() { synchronized(this) { int i = 5; while( i-- > 0) { System.out.println(Thread.currentThread().getName() + " : " + i); try { Thread.sleep(500); } catch (InterruptedException ie) { } } } } public synchronized void test2() { int i = 5; while( i-- > 0) { System.out.println(Thread.currentThread().getName() + " : " + i); try { Thread.sleep(500); } catch (InterruptedException ie) { } } } public synchronized void test3() { int i = 5; while( i-- > 0) { System.out.println(Thread.currentThread().getName() + " : " + i); try { Thread.sleep(500); } catch (InterruptedException ie) { } } } public static void main(String[] args) { final TestSynchronized myt2 = new TestSynchronized(); final TestSynchronized myt3 = new TestSynchronized(); Thread test1 = new Thread( new Runnable() { public void run() { myt2.test2(); } }, "test1" ); Thread test2 = new Thread( new Runnable() { public void run() { myt2.test3(); } }, "test3" ); test1.start();; test2.start(); } } Running results:
test1 : 4test1 : 3test1 : 2test1 : 1test1 : 0test3 : 4test3 : 3test3 : 2test3 : 1test3 : 0
Below we focus on the usage of Sychronized in Java, which is specifically: the synchronization method and the synchronized block synchronized keyword, which includes two usages: the synchronized method and the synchronized block.
1. Synchronized method: Declare the synchronized method by adding the synchronized keyword to the method declaration. like:
public synchronized void accessVal(int newVal);
The synchronized method controls access to class member variables: each class instance corresponds to a lock, and each synchronized method must obtain the lock of the class instance that calls the method before it can be executed. Otherwise, the thread to which it belongs is blocked. Once the method is executed, it will exclusively occupy the lock. The lock will not be released until it returns from the method. The blocked thread can obtain the lock and re-enter the executable state. This mechanism ensures that at the same time, for each class instance, at most one of all member functions declared synchronized is in an executable state (because at most one can obtain the lock corresponding to the class instance), thus effectively avoiding access conflicts of class member variables (as long as all possible methods to access class member variables are declared synchronized).
In Java, not only class instances, each class also corresponds to a lock, so we can declare the static member function of the class as static synchronized to control its access to the static member variables of the class.
The disadvantage of synchronized method: Declaring a large method as synchronized will greatly affect efficiency. Typically, if the thread class's method run() is declared as synchronized, since it has been running throughout the life of the thread, it will cause it to never succeed in any synchronized method of this class. Of course we can solve this problem by putting the code that accesses the class member variables into a special method, declaring it as synchronized, and calling it in the main method, but Java provides us with a better solution, that is, the synchronized block.
2. Synchronized block: Declare the synchronized block through the synchronized keyword. The syntax is as follows:
synchronized(syncObject) { //Code that allows access control} The synchronized block is a code block in which the code must obtain a lock of the object syncObject (as mentioned earlier, it can be a class instance or class) before it can be executed. The specific mechanism is the same as described above. Since it can be targeted at any code block and locked objects can be specified at any time, it is more flexible.
Notice:
When using synchronized keywords, you should avoid using sleep or yield methods in synchronized methods or synchronized blocks as much as possible, because synchronized program blocks occupy object locks, so if you rest, other threads can only be executed while waiting for you to wake up and finish executing. Not only does it seriously affect efficiency, it is also not logical.
Similarly, it doesn't make sense to call the yeild method in the synchronous program block to give up the CPU resource, because you occupy the lock and other mutex threads still cannot access the synchronous program block. Of course, threads that are not related to synchronous program blocks can obtain more execution time.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.