When a Java language keyword is used to modify a method or a code block, it can ensure that at most one thread executes the code at the same time.
1. Use it when declaring the method, after the scope operator (public, etc.), before the return type declaration (void, etc.). At this time, the thread obtains a member lock, that is, only one thread can enter the method at a time, and other threads If you want to call this method at this time, you can only wait in line. After the current thread (that is, the thread inside the synchronized method) has executed the method, other threads can enter.
For example:
public synchronized void synMethod() { //Method body}2. Use synchronized followed by brackets, and variables are included in brackets. In this way, only one thread enters the code block at a time. At this time, the thread obtains a member lock. For example:
public int synMethod(int a1){ synchronized(a1) { //Only one thread can enter at a time} } 3. There is an object in the brackets after synchronized. At this time, the thread obtains the object lock. For example:
public class MyThread implements Runnable { public static void main(String args[]) { MyThread mt = new MyThread(); Thread t1 = new Thread(mt, "t1"); Thre ad t2 = new Thread(mt, "t2") ; Thread t3 = new Thread(mt, "t3"); Thread t4 = new Thread(mt, "t4"); Thread t5 = new Thread(mt, "t5"); Thread t6 = new Thread(mt, "t6 "); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); t6.start(); } public void run() { synchronized (this) { System.out.println(Thread.currentThread().getName()); } }}For 3, if the thread enters, it gets the current object lock, and then any operations of other threads on all objects in the class cannot be performed. Using locks at the object level is usually a relatively rough method. Why lock the entire object without allowing other threads to briefly use other synchronization methods in the object to access shared resources? If an object has multiple resources, it does not need to lock all threads outside just to have a thread use some of the resources. Since each object has a lock, you can use a virtual object to lock it as follows:
class FineGrainLock { MyMemberClass x, y; Object xlock = new Object(), ylock = new Object(); public void foo() { synchronized(xlock) { // access x here } //do something here - but don't use shared resources synchronized(ylock) { //access y here } } public void bar() { synchronized(this) { //access both x and y here } //do someth ing here - but don't use shared resources } }4. The class is in the brackets after synchronized. At this time, the thread obtains the object lock. For example:
class ArrayWithLockOrder{ private static long num_locks = 0; private long lock_order; private int[] arr; public ArrayWithLockOrder(int[] a) { arr = a ; synchronized(ArrayWithLockOrder.class) {//---- Here num_locks++; // Add 1 to the lock number. lock_order = num_locks; // Set a unique lock_order for this object instance. } } public long lockOrder() { return lock_order; } public int[] array() { return arr; } } class SomeClass implements Runnable { public int sumArrays (ArrayWithLockOrder a1, ArrayWithLockOrder a2) { int value = 0; ArrayWithLockOrder first = a1 ; // Keep an ArrayWithLockOrder reference last = a2; // Local copy. int size = a1.array().length; if (size == a2.array().length) { if (a1.lockOrder() > a2.lockOrder()) // Determine and set the lock of the object { // order. first = a2; last = a1; } synchronized(first) { // Lock the object in the correct order. synchronized(last) { int[] arr1 = a1.array(); int[] arr2 = a2.array(); for (int i=0; i<size; i++) value += arr1[i] + arr2[ i]; } } } return value; } public void run() { // } }For 4, if the thread enters, all operations in the thread cannot be performed in the class, including static variables and static methods. In fact, for the synchronization of code blocks containing static methods and static variables, we usually use 4 to lock.
PS: Synchronized Usage Summary
Synchronized uses different places to affect the code:
1. Synchronized keyword modification method
Assuming that P1 and P2 are different objects of the same class, this class defines the synchronization block or synchronization method in the following situations, and P1 and P2 can call them.
public synchronized void method(){ // }This is the synchronization method. At this time, synchronized locks the synchronization method object. That is to say, when an object P1 executes this synchronization method in different threads, they will form mutual exclusion to achieve the effect of synchronization. At the same time, if there are multiple synchronization methods in the object, when a thread executes a synchronized method in the object, other synchronization methods in the object are not allowed to be executed by other threads. However, another object P2 generated by Class to which this object belongs can arbitrarily call this method with the synchronized keyword added.
The above example code is equivalent to the following code:
public void method() { synchronized (this) { //.. } }This time it is a P1 object lock. Only if the thread that has obtained the P1 object lock can it call the P1 synchronization method. For P2, the P1 lock has nothing to do with it, and the program may also be in this situation. Get rid of the control of the synchronization mechanism and cause data confusion.
2. Synchronize blocks, the sample code is as follows:
public void method() { synchronized (this) { //.. } }At this time, the lock is the so object, and each object corresponds to a unique lock, so whoever thread gets this object lock will be able to run the code he controls. When there is a clear object as a lock, you can write the program like this, but when there is no clear object as a lock, you just want a piece of code to synchronize, you can create a special instance variable (it must be an object) to act as a lock:
private byte[] lock = new byte[0]; Public void method(){ synchronized(lock) { // } } Note: Zero-length byte array objects are more economical than any object to create. View compiled byte codes: only 3 opcodes are required to generate zero-length byte[] objects, while Object lock = new Object() requires 7 Line opcode.
3. Use synchronized to static function, the example code is as follows:
Class Foo { public synchronized static void method1() { //. } public void method2() { synchronized(Foo.class) // } } Both synchronous methods call the class lock of the class to which the object of this method belongs (Class, no longer a specific object generated by this Class).
It can be inferred that if a class defines a synchronized static function A and also defines a synchronized instance function B, then the same object Obj of this class will not constitute a method A and B respectively when accessing two methods A and B in multiple threads. Synchronize because their locks are different. The lock of method A is the Class to which Obj belongs, and the lock of B is the object to which Obj belongs.