The synchronized keyword has two uses. The first is to use it directly in the definition of the method as introduced in the article "Using the Synchronized keyword to synchronize class methods". Another type is synchronized block. We can not only synchronize an object variable through synchronized blocks. You can also use synchronized blocks to synchronize static and non-static methods in a class.
The syntax of synchronized block is as follows:
Copy the code code as follows:
public void method()
{
… …
synchronized(expression)
{
… …
}
}
1. Synchronization of non-static class methods
From the article "Using the Synchronized keyword to synchronize class methods" we know that using the synchronized keyword to define methods will lock all static or non-static methods defined using the synchronzied keyword in the class, but this is not easy to understand. If you use synchronized blocks to achieve the same effect, it is not difficult to understand why this effect occurs. If you want to use a synchronized block to lock all synchronized non-static methods in a class, you need to use this as a parameter of the synchronized block and pass it into the synchronized block country. The code is as follows:
Synchronize non-static methods through synchronized blocks
Copy the code code as follows:
public class SyncBlock
{
public void method1()
{
synchronized(this) // Equivalent to using the synchronized keyword on the method1 method
{
… …
}
}
public void method2()
{
synchronized(this) // Equivalent to using the synchronized keyword for the method2 method
{
… …
}
}
public synchronized void method3()
{
… …
}
}
In the above code synchronized blocks are used in method1 and method2 methods. The method3 method on line 017 still uses the synchronized keyword to define the method. When using the same SyncBlock class instance, as long as one of the three methods is executing, the other two methods will be blocked because the synchronization lock is not obtained. To achieve the same effect as the synchronized keyword when using the synchronized block, all code must be written in the synchronized block. Otherwise, all the code in the current method will not be synchronized with other methods.
In addition to using this as a parameter of the synchronized block, you can also use SyncBlock.this as a parameter of the synchronized block to achieve the same effect.
When using the synchronized block in the method of the inner class (InnerClass), this only represents the inner class and has nothing to do with the outer class (OuterClass). But non-static methods of the inner class can be synchronized with non-static methods of the outer class. For example, add a method4 method to the inner class InnerClass and synchronize the method4 method with the three methods of SyncBlock. The code is as follows:
Synchronize non-static methods of inner class with non-static methods of outer class
Copy the code code as follows:
public class SyncBlock
{
… …
classInnerClass
{
public void method4()
{
synchronized(SyncBlock.this)
{
… …
}
}
}
… …
}
In the new version of the SyncBlock class above, the method 4 method of the InnerClass class is synchronized with the other three methods of the SyncBlock class. Therefore, only one method of the four methods method1, method2, method3 and method4 can be executed at the same time.
Whether the synchronized block is executed normally or exits the synchronized block abnormally due to a program error, the synchronization lock held by the current synchronized block will be automatically released. Therefore, you don't have to worry about the release of synchronization locks when using synchronized blocks.
2. Synchronization of static class methods
Because when calling a static method, the object instance is not necessarily created. Therefore, you cannot use this to synchronize static methods, but you must use Class objects to synchronize static methods. The code is as follows:
Synchronize static methods through synchronized blocks
Copy the code code as follows:
public class StaticSyncBlock
{
public static void method1()
{
synchronized(StaticSyncBlock.class)
{
… …
}
}
public static synchronized void method2()
{
… …
}
}
When synchronizing static methods, you can use the static field class of the class to get the Class object. In the above example, only one method of method1 and method2 can be executed at the same time. In addition to using the class field to get the Class object, you can also use the getClass method of the instance to get the Class object. The code in the above example can be modified as follows:
Use the getClass method to get the Class object
Copy the code code as follows:
public class StaticSyncBlock
{
public static StaticSyncBlock instance;
public StaticSyncBlock()
{
instance = this;
}
public static void method1()
{
synchronized(instance.getClass())
{
}
}
}
In the above code, an instance of the StaticSyncBlock class is obtained through a public static instance, and the Class object is obtained through the getClass method of this instance (all instances of a class obtain the same Class object through the getClass method, therefore, calling any The getClass method of an instance can be used). We can also synchronize static methods of different classes through Class objects, such as the static method method of the Test class and the two static methods of the StaticSyncBlock class. The code is as follows:
The method method of the Test class is synchronized with the method1 and method2 methods of the StaticSyncBlock class.
Copy the code code as follows:
public class Test
{
public static void method()
{
synchronized(StaticSyncBlock.class)
{
}
}
}
Note: When using synchronized block synchronization class methods, non-static methods can use this to synchronize, while static methods must use the Class object to synchronize. They do not affect each other. Of course, you can also use Class objects in non-static methods to synchronize static methods. But this cannot be used in static methods to synchronize non-static methods. This should be noted when using synchronized block synchronization class methods.