Understanding of locks in multithreading

Locks are very important in multithreading.

In the Java language, there are objects and classes, so multi-threaded locks can also be divided into object locks and class locks.

Object lock, as the name implies, is to use an object as a lock for use in multiple threads; and class lock, this is mainly a lock added to a class-level method or code block, such as a static method or static code block.

Because it is multi-threaded, the lock is a shared resource, and multiple threads compete for the same lock. If multiple threads use multiple locks, then program code execution has little to do with multiple threads.

Here's a very simple example (a bit inelegant):

When you go to the bathroom, you can squat in a large size, and each pit can only be used by one person. If someone goes in, he will lock the door, then this lock can be understood as the concept of lock in multi-threading. There are still many people who want to use this hut, but there are people inside, so the rest have to wait outside. Only the people inside are comfortable, and the door is opened, the lock will be released at this time, and other people will compete for the lock. Some people can't hold back and can only give up (understood as thread timeout, thread gives up).

Summarize:

When using the synchronized keyword, the lock used must be a lock shared by multiple threads.

There are several ways to write it:

1) Multiple threads compete for the resources of the same object. That is to say, the data of an object needs to be switched and modified between multiple threads. How to achieve it?

public class ShareBody {

    public void print(int count) throws Exception {
        synchronized (this) {
            System.out.println(Thread.currentThread().getName() + "开始打印");
            for (int i = 1; i < count; i++) {
                System.out.println(Thread.currentThread().getName() + " " + i);
            }
            Thread.sleep(2000);
        }
    }
}

public class ThreadA implements Runnable {

    private ShareBody shareBody;

    public ThreadA(ShareBody shareBody) {
        this.shareBody = shareBody;
    }

    @Override
    public void run() {
        while (true) {
            try {
                this.shareBody.print((int)(Math.random() * 100));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

public class Main {
    public static void main(String[] args) {
        ShareBody shareBody = new ShareBody();
        ThreadA a = new ThreadA(shareBody);
        ThreadA b = new ThreadA(shareBody);
        ThreadA c = new ThreadA(shareBody);
        a.start();
        b.start();
        c.start();
    }
}

Note that the synchronized keyword in the ShareBody class uses this as the lock, that is to say, the shareBody object in the Main class is used as the lock, and the three threads use the same object, so the competition for the lock is also the same. Therefore, the three threads will randomly select a thread to print a random number of times (the random number here is because the random number is set in the thread class).

2) Multiple threads, each thread uses a different object, but uses the same lock. E.g:

public class ObjectA {
    private Object _lock;
    public ObjectA(Object lock) {
        this._lock = lock;
    }

    public void methodA() throws Exception {
        synchronized(_lock) {
            //todo something
            Thread.sleep(2000);
        }
    }
}

public class ObjectB {
    private Object _lock;
    public ObjectB(Object lock) {
        this._lock = lock;
    }

    public void methodB() throws Exception {
        synchronized(_lock) {
            //todo something
            Thread.sleep(3000);
        }
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        Object lock = new Object();//创建锁对象
        ObjectA objA = new ObjectA(lock);//创建对象A
        ObjectB objB = new ObjectB(lock);//创建对象B
        new Thread(new Runnable(){
            @Override
            public void run(){
                objA.methodA();
            }
        }).start();
        new Thread(new Runnable(){
            @Override
            public void run(){
                objB.methodB();
            }
        }).start();
    }
}

The two threads created in the main method operate different methods on two different objects, but the synchronized methods they call use the same object lock. So two threads are blocking synchronization, one thread executes and the other thread waits.

The above are object locks. What about class locks?

Class locks are actually locking on class-level operations. The most common is the use of the static keyword. If you add the keyword static to a method of a class, then this method is a class method. Class-level operations are shared by every object. Therefore, if you add synchronized to a static method, then all objects calling this method are synchronized, and this class lock works on all object instances.

Guess you like

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