Summary of how to use synchronized in Java
1. When using synchronized as a function modifier, the sample code is as follows:
Public synchronized void method(){ //…. }
This is the synchronization method. So which object is synchronized locked at this time? What he locks is calling this synchronized method object. In other words, when an object P1 executes this synchronization method in different threads, they will form mutual exclusion to achieve synchronization effect. However, another object P2 generated by the Class to which this object belongs can arbitrarily call this method with the synchronized keyword added.
The sample code above is equivalent to the following code:
public void method() { synchronized (this) // (1) { //….. } }
What does this at (1) refer to? He refers to the object that calls this method, such as P1. It can be seen that the essence of the synchronization method is to apply synchronized to the object reference. ——Only the thread that has obtained the P1 object lock can call the synchronization method of P1. As far as P2 is concerned, the P1 lock has nothing to do with it. The program may also get rid of the control of the synchronization mechanism in this case, resulting in data confusion.
2. Synchronization block, the sample code is as follows:
public void method(SomeObject so) { synchronized(so) { //….. } }
At this time, the lock is the so object, and whoever gets the lock can run the code he controls. When there is a clear object as the lock, you can write the program like this, but when there is no clear object as the lock and you just want to synchronize a piece of code, you can create a special instance variable (it must be an object) to act as the lock:
class Foo implements Runnable { private byte[] lock = new byte[0]; // 特别的instance变量 Public void method() { synchronized(lock) { //… } } //….. }
Note: A zero-length byte array object will be more economical to create than any object - view the compiled bytecode: generating a zero-length byte[] object requires only 3 opcodes, while Object lock = new Object() requires 7 lines of opcode.
3. Apply synchronized to a static function. The sample code is as follows:
Class Foo { public synchronized static void method1() // 同步的static 函数 { //…. } public void method2() { synchronized(Foo.class) // class literal(类名称字面常量) } }
The method2() method in the code uses class literal as a lock. The effect it produces with the synchronized static function is Similarly, the lock acquired is very special, it is the class (Class, rather than a specific object generated by this Class) to which the object currently calling this method belongs.
I remember that I saw in the book "Effective Java" that using Foo.class and P1.getClass() for synchronization locks is not the same. You cannot use P1.getClass() to achieve the purpose of locking this Class. P1 refers to the object generated by the Foo class.
It can be inferred: If a synchronized static function A is defined in a class, and a synchronized instance function B is also defined, then when the same object Obj of this class accesses the A and B methods respectively in multiple threads, There will be no synchronization because their locks are different. The lock of method A is the Class to which Obj belongs, and the lock of method B is the object to which Obj belongs.
A summary of how to use synchronized in Java is as follows:
Knowing which object synchronized locks can help us design safer multi-threaded programs.
There are some more techniques that can make our synchronous access to shared resources more secure:
1. Define private instance variables and their get methods instead of public/protected instance variables. If the variable is defined as public, the object can directly obtain it and change it from the outside world, bypassing the control of the synchronization method. This is also one of the standard implementation methods of JavaBean.
2. If the instance variable is an object, such as an array or ArrayList, then the above method is still unsafe, because when the external object gets the reference of the instance object through the get method and points it to another object, then the private variable is If it changes, wouldn't it be dangerous? At this time, you need to add synchronized synchronization to the get method, and only return the clone() of this private object - in this way, the calling end gets a reference to the object copy.
The above is the detailed content of How to use synchronized to implement synchronization mechanism in Java?. For more information, please follow other related articles on the PHP Chinese website!