Multithreading-thread synchronization lock Lock lock

Multithreading-thread synchronization lock-Lock lock-ReentrantLock

The thread synchronization mechanism Synchronize lock was mentioned before. In fact, there is also a JUC Lock lock that can also achieve thread synchronization. Moreover, the Lock implementation class ReentrantLock is more flexible and richer than Synchronize, and is more suitable for use in most scenarios.
Let's briefly compare ReentrantLock and Synchronize.

  1. Synchronsize lock is an exclusive lock. Locking and releasing locks are automatic, as long as the keyword synchronize or a code block is added. It is very simple to use, but it is less flexible. ReentrantLock is also an exclusive lock, but it requires manual locking (lock, etc.) and unlocking (unlock). It is relatively complicated to use, but it is flexible and ReentrantLock provides a wealth of methods.
  2. Synchronsize and ReentrantLock are both reentrant locks (locks can be used multiple times: for example, method A uses a lock, but actually calls B, but B also uses a lock, which means that you don't need to reacquire the lock when calling B). But all need to release the lock to allow other threads to get the lock.
  3. Once Synchronize cannot get the lock and a deadlock waiting state is generated, the corresponding cannot be interrupted, and ReentrantLock provides the corresponding mid-order lock.
  4. The most important thing is that ReentrantLock can also implement a fair lock mechanism. What is fair lock? That is, the thread that has waited the longest on the lock will get the right to use the lock. The popular understanding is that whoever has been in the longest queue will acquire the lock first.

Unlike Synchronize, ReentrantLock provides multiple locks that can handle thread synchronization issues according to different needs. Below we focus on the ReentrantLock lock. For the introduction of Synchronize, please check the previous blog Thread Insecurity + Thread Deadlock + Synchronization .

ReentrantLock is a class under the JUC package (java.util.concurrent.locks.ReentrantLock), which implements the Lock interface.
Insert picture description here
ReentrantLock release locks are all the same unlock method, the following mainly looks at the different locks of ReentrantLock.
When thread synchronization is not implemented, no locking effect:

public class ReenTrantLockThread {
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        new Thread(threadTest,"小明").start();
        new Thread(threadTest,"小王").start();
    }
}

class ThreadTest implements Runnable{
    final Lock lock = new ReentrantLock();
    @Override
    public void run() {
        study();
    }

    public void study(){
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+":我正在学习");
        }
    }
}

Result:
Insert picture description here
Xiao Ming and Xiao Wang were mad and learned by cpu scheduling. After the lock is added, let one person finish learning and then the next thread will take the lock to learn (note that the next thread is not necessarily another person, it is scheduled by the cpu)

(1) Lock() This lock is a common and commonly used lock, similar to the Synchronize lock. Once the lock is obtained, you must wait for the lock to be released before you can continue to hold the lock, otherwise thread deadlock will occur, so the lock must be released after the end of use .
Note: In order to prevent the lock from being released, generally put the lock content in the try, and then release the lock in the finally, so as to ensure that the lock will be released.

    public void study(){
        lock.lock();
        try {    /
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName()+":我正在学习");
            }
        }catch (Exception e){
        }finally {
            lock.unlock()
        }
    }  

Result: Let one person finish learning and then learn with the lock in the next thread!!!
Insert picture description here

(2) tryLock() lock, I call it try lock. It is used to try to acquire the lock. If it can be acquired, then the lock can be occupied and used. If it is not available, we can also handle other things. It has a return value, type boolean, if it gets the lock, it returns true, and if it can't get it, it returns false, so it will immediately return a value no matter what.

public void study(){
        boolean flag = lock.tryLock();
        if(flag){
            try {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName()+":我正在学习");
                }
            }catch (Exception e){

            }finally {
                lock.unlock();
            }
        }else {
            System.out.println(Thread.currentThread().getName()+":我没拿到锁,那我去看电视了");
        }
    }

Result:
Insert picture description here
(3) tryLock(long timeout, TimeUnit unit), the usage is the same as tryLock, the difference is that you can specify the waiting time, that is, lock me and hold the lock, if the lock is not obtained after the specified time, I will return false, time Before that, I continued to wait for the lock to be released.

public void study() throws InterruptedException {
        boolean flag = lock.tryLock(5000,TimeUnit.MILLISECONDS); // 等待5秒钟拿不到锁就返回false
        if(flag){
            try {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName()+":我正在学习");
                }
            }catch (Exception e){

            }finally {
                lock.unlock();
            }
        }else {
            System.out.println(Thread.currentThread().getName()+":我没拿到锁,那我去看电视了");
        }
    }

Result: The lock was successfully obtained within 5 seconds.
Insert picture description here
We add a sleep to the thread, let the thread rest for more than 5 seconds,
Insert picture description here
(4) lockInterruptibly() interrupt lock, use this lock to actively interrupt the thread using Thread.interrupt(). The premise is that this thread uses a lock, and it cannot be used without a lock. This is not easy to demonstrate, the usage is as follows:
Insert picture description here
Then talk about ReentrantLock's special locking mechanism , fair lock and unfair lock.
Just like the literal meaning,
fair lock means that which thread queues for a long time will let whoever has the advantage to schedule.
Unfair lock means that no matter when threads start to queue, I let the cpu look at the mood schedule.
The method of use is very simple, you only need to add the true (fair) or false (unfair) parameter when initializing the lock. The default is false
fair lock:

final Lock lock = new ReentrantLock(true);
public void study() throws InterruptedException {
        for (int i = 0; i <2 ; i++) {
            try {
                lock.lock(); // 等待5秒钟拿不到锁就返回false
                System.out.println(Thread.currentThread().getName()+":我正在学习");
                //Thread.sleep(2000);
            }catch (Exception e){

            }finally {
                lock.unlock();
            }
        }
    }

Result: Don't squeeze, everyone has a share.
Insert picture description here
Unfair lock:

    final Lock lock = new ReentrantLock(false);
    public void study() throws InterruptedException {
        for (int i = 0; i <2 ; i++) {
            try {
                lock.lock(); // 等待5秒钟拿不到锁就返回false
                System.out.println(Thread.currentThread().getName()+":我正在学习");
                //Thread.sleep(2000);
            }catch (Exception e){

            }finally {
                lock.unlock();
            }
        }
    }

Result: The next
Insert picture description herefilm introduction: read-write lock.

Guess you like

Origin blog.csdn.net/qq_31142237/article/details/114648496