The most basic synchronization method in Java is to use the synchronized keyword to control concurrent access to a method. Every method declared with the synchronized keyword is a critical section. In Java, only one critical section of the same object is allowed to be accessed at the same time.
Static methods have different behaviors. Static methods declared with the synchronized keyword can only be accessed by one execution thread at the same time, but other threads can access the non-static synchronized methods of this object. You must be very careful about this because two threads can access two different synchronized methods of an object at the same time, that is, one of them is a static synchronized method and the other is a non-static synchronized method. If both methods change the same data, a data inconsistency error will occur.
The synchronized block syntax is as follows:
public void method() { synchronized(表达式) { } }
The synchronized keyword has two uses, one is only used in the definition of the method, the other is the synchronized block, we can not only use synchronized To synchronize an object variable, you can also synchronize static methods and non-static methods in a class through synchronizedl.
The first: synchronization of non-static methods
From the Java related grammar, we can know that using the synchronized keyword to define methods will lock the static methods and non-static methods defined using the synchroniezd keyword in the class. Static method, but this is a bit difficult to understand. If you want a synchronized block to achieve such an effect, it is not difficult to understand why this effect occurs. If you use synchronized to lock all synchronous non-static methods in the class, you only need to use This is passed into the synchronized block as a parameter of the synchronized block. The code is as follows:
public class Test { public void method1() { synchronized(this) { } } public synchronized void method2() { } } public class Test { public void method1() { synchronized(this) { } } public synchronized void method2() { } }
In the above code, method1 uses the synchronized block, and the method2 method uses the synchronized keyword to define the method. If the same one is used, When Testing an instance, as long as one of these two methods is executing, the other methods will be blocked because they have not obtained the synchronization lock. In addition to using this as a parameter of the synchronized block, you can also use Test.this as a parameter of the synchronized block to achieve the same effect.
In synchronized blocks used in inner classes, this only represents the inner class and has nothing to do with the outer class (OuterClass). But non-static methods in the inner class and non-static methods in the outer class can also be synchronized. If you add a method method3 in the inner class, you can also synchronize it with the two methods in Test. The code is as follows:
public class Test { class InnerClass { public void method3() { synchronized(Test.this){ } } } } public class Test { class InnerClass { public void method3() { synchronized(Test.this){ } } } }
The above method3 method of InnerClass and the method1 and method2 method of Test can only exist at the same time. A method is executed.
Whether the synchronized block is executed correctly or exits the synchronized block due to an exception due to a program error, the synchronization lock held by the current synchronized block will be automatically released, so there is no need to worry about the synchronization lock issue when using the synchronized block.
2. Synchronization of static methods
Since the object instance is not necessarily created when calling the static method, therefore, you cannot use this to synchronize the static method, but you must use the Class object to synchronize the static method. The code is as follows:
public class Test{ pubic static void method1(){ synchronized(Test.class){ } } public static synchronized void method2(){ } } public class Test{ pubic static void method1(){ synchronized(Test.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, method1 and method2 methods have only one method to execute. In addition to using the class field to get the class object, you can also The class object can be obtained through the getClass() method of the instance. The code is as follows:
public class Test{ public static Test test; public Test(){ test=this; } public static void method1(){ synchronized(test.getClass()){ } } } public class Test{ public static Test test; public Test(){ test=this; } public static void method1(){ synchronized(test.getClass()){ } } }
In the above code, we get an instance of Test through a public static object and obtain an instance through the getClass method of this instance. class object (note that all instances of a class obtain the same Class object through the getClass method). We can also synchronize static methods of different classes through class. The code is as follows:
public class Test1{ public static void method1(){ synchronized(Test.class){ } } } public class Test1{ public static void method1(){ synchronized(Test.class){ } } }
Note: When using synchronized blocks to synchronize methods, non-static methods can be synchronized through this, while static methods must use class objects. To synchronize, but non-static methods can also synchronize static methods by using class. But this cannot be used in static methods to synchronize non-static methods. This needs to be noted when using synchronized blocks.
Note
The synchronized keyword will reduce the performance of the application, so it can only be used in concurrent scenarios on methods that need to modify shared data. If multiple threads access the same synchronized method, only one thread can access it and other threads will wait. If the method declaration does not use the synchronized keyword, all threads can execute the method at the same time, thus reducing the total running time. If it is known that a method will not be called by more than one thread, there is no need to declare it with the synchronized keyword.
Methods declared by synchronized can be called recursively. When a thread accesses the synchronized method of an object, it can also call other synchronized methods of the object, including the method being executed, without having to obtain access to this method again.
我们可以通过synchronized关键字来保护代码块(而不是整个方法)的访问。应该这样利用synchronized关键字:方法的其余部分保持在synchronized代码块之外,以获取更好的性能。临界区(即同一时间只能被一个线程访问的代码块)的访问应该尽可能的短。例如在获取一幢楼人数的操作中,我们只使用synchronized关键字来保护对人数更新的指令,并让其他操作不使用共享数据。当这样使用synchronized关键字时,必须把对象引用作为传入参数。同一时间只有一个线程被允许访问这个synchronized代码。通常来说,我们使用this关键字来引用正在执行的方法所属的对象:
synchronized(this){ //Java code }
更多Java中synchronized关键字修饰方法同步的用法详解相关文章请关注PHP中文网!