The synchronized keyword of java multithreading (2)

Introduction of synchronized

When there are multiple threads operating shared data, it is necessary to ensure that there is only one thread operating the shared data at the same time, and other threads must wait until the thread has processed the data before proceeding. This method is called mutual exclusion, that is to say, when a After the shared data is added to the mutex by the currently accessing thread, at the same time, other threads can only wait until the current thread finishes processing and releases the lock. In Java, the keyword synchronized can ensure that at the same time, only one thread can execute a method or a code block (mainly operations on shared data in methods or code blocks), and we should also note that synchronized Another important role, synchronized can ensure that changes in one thread (mainly changes in shared data) are seen by other threads (guarantee visibility, which can completely replace the Volatile function)

3 application methods of synchronized

The synchronized keyword mainly has the following three application methods, which are introduced separately below.

  • Modify the instance method, lock the object that calls the method, and obtain the lock (this) of the current object before entering the synchronization code

  • Modify the static method, lock the current class object, and obtain the lock of the current class object (Class object) before entering the synchronization code

  • Modify the code block, specify the lock object, lock the given object, and obtain the lock of the given object before entering the synchronization code base.

synchronized decorates non-static methods

public class AccountingSync implements Runnable{
    //Shared resources (critical resources)
    static int i=0;

    /**
     * synchronized decorates non-static methods
     */
    public synchronized void increase(){
        i++;
    }
    @Override
    public void run() {
        for(int j=0;j<1000000;j++){
            increase();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        AccountingSync instance=new AccountingSync();
        Thread t1=new Thread(instance);
        Thread t2=new Thread(instance);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }
    /**
     * output result:
     * 2000000
     */
}

The same object accesses the synchronization method of the object in two threads, the first thread obtains the object lock and accesses the synchronization method, and the second thread cannot access the synchronization method because it cannot obtain the object lock. You need to wait for the first thread to finish executing and release the lock before it can be accessed, thus forming a mutual exclusion!

Description: The lock of a non-static method is the object

If the first thread accesses the synchronized method of the A object, and the second thread accesses the synchronized method of the B object, it will not cause mutual exclusion. as follows

public static void main(String[] args) throws InterruptedException {
        //new new instance
        Thread t1=new Thread(new AccountingSyncBad());
        //new new instance
        Thread t2=new Thread(new AccountingSyncBad());
        t1.start();
        t2.start();
        //join meaning: the current thread A waits for the thread thread to terminate before returning from thread.join()
        t1.join();
        t2.join();
        System.out.println(i);
    }

The first thread and the second thread respectively get their own new object locks, and the synchronization methods have their own locks, which will not cause mutual exclusion.

synchronized decorates static methods

public class AccountingSyncClass implements Runnable{
    static int i=0;

    /**
     * Acting on static methods, the lock is the current class object, that is
     * The class object corresponding to the AccountingSyncClass class
     */
    public static synchronized void increase(){
        i++;
    }

    /**
     * Non-static, mutual exclusion will not occur when the lock is different when accessing
     */
    public synchronized void increase2(){
        i++;
    }

    @Override
    public void run() {
        for(int j=0;j<1000000;j++){
            increase();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(new AccountingSyncClass());
        Thread t2=new Thread(new AccountingSyncClass());
        // start the thread
        t1.start();t2.start();

        t1.join();t2.join();
        System.out.println(i);
    }
}

Although the above two threads each have different objects, they access the static method. The lock of the static method is the current class object. The two threads access the synchronized static method and get the lock of the current class object. There is only one lock. Of course they are mutually exclusive!

synchronized modified code block

In some cases, the method body we write may be relatively large, and there are some time-consuming operations, and there is only a small part of the code that needs to be synchronized. If we directly synchronize the entire method, it may not be worth the loss. We can wrap the code that needs to be synchronized by using a synchronized code block, so that the entire method does not need to be synchronized.

public class AccountingSync implements Runnable{
    static AccountingSync instance=new AccountingSync();
    static int i=0;
    @Override
    public void run() {
        //Omit other time-consuming operations....
        //Use the synchronization code block to synchronize the variable i, and the lock object is instance
        synchronized(instance){
            for(int j=0;j<1000000;j++){
                    i++;
              }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(instance);
        Thread t2=new Thread(instance);
        t1.start();t2.start();
        t1.join();t2.join();
        System.out.println(i);
    }
}
When synchronized modifying the code block, you need to specify the lock object. When multi-threaded access, you need to get the lock object before you can access the static code block. If other threads are currently holding the object lock, the newly arrived thread must wait. , which also ensures that only one thread executes at a time. Usually we often use this and xx.class objects as lock objects,
//this, the current instance object lock
synchronized(this){
    for(int j=0;j<1000000;j++){
        i++;
    }
}

//class object lock
synchronized(AccountingSync.class){
    for(int j=0;j<1000000;j++){
        i++;
    }
}

The meanings of synchronized methods and synchronized code blocks are the same. Synchronized methods do not need to explicitly specify the lock object, while code blocks need to be explicitly specified. The effect and meaning are the same.


Summarize:

Whether the multi-threaded access synchronization method can be accessed at the same time mainly depends on whether the lock object obtained by the thread is unique. If the lock object is unique, it means that multiple threads will mutually exclusive access!

1. Threads calling non-static synchronization methods in the same object are mutually exclusive. If it is a different object, each thread has its own lock on the object, and the threads do not interfere with each other.

2. Threads calling static synchronization methods in the same class will be mutually exclusive, and they are all locked on the same Class object. 

3. Static synchronized methods and non-static synchronized methods will never be mutually exclusive, because static methods are locked on Class objects and non-static methods are locked on objects of that class.

4. For synchronized code blocks, see what object has been used for locking ( the content of the parentheses after synchronized). Threads synchronizing on the same object will be mutually exclusive, threads locking on different objects will never be mutually exclusive.




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325721678&siteId=291194637