Detailed explanation on the usage of Lock lock (case-driven, step-by-step teaching)

Come on, baby, sell tickets!

Insert image description here

100 tickets, 4 windows
- emmmmm, can there be 5 windows?
also! Hehe, just be happy!
——Hey, no, I see there are 8 windows in the picture above...
wocao, he...tui, I said 4 means 4!

Insert image description here

Get ready, let’s get started, let your girlfriend help you open our development tool: IDEA2020.2
Insert image description here

By the way: If you also want to have the right to use your idea for such a long time, you can follow my WeChat official account: [Youyou has something to say ], reply with the keyword " IDEA " to get the same results as me The effect!
Insert image description here

Oke Oke, go on.

Create a new java class and name it woaiyouyouxiaogege.java . How about it? Even if you don’t have level 8 pinyin , you can’t understand my code! ( I love little brother Youyou.java ) Hahahahaha burp

Just kidding, be normal, create a new java class and name it LockDemo.java

public class LockDemo{
    
    

    public static void main(String[] args) {
    
    
        
    }

Since we are talking about locks, we must have threads ( multi-threads ). So, I will let this class implement the Runnable interface and override the run method.

public class LockDemo implements Runnable{
    
    

    public static void main(String[] args) {
    
    
        
    }
     @Override
     public void run() {
    
    
         
      }

Then, create a thread object, call the thread start method , and give the thread a name to facilitate distinction (Girlfriend No. 1, Girlfriend No. 2, Girlfriend No. 3...)
Insert image description here

public class LockDemo implements Runnable{
    
    

    public static void main(String[] args) {
    
    
        LockDemo lockDemo=new LockDemo();
        new Thread(lockDemo,"售票窗口").start();
    }
     @Override
      public void run() {
    
    
         
      }

——It seems... there is a... small problem?

What? Oh oh oh oh, I understand, multi-threading, a few more windows! What a big deal!

public class LockDemo implements Runnable{
    
    

    public static void main(String[] args) {
    
    
        LockDemo lockDemo=new LockDemo();
        new Thread(lockDemo,"窗口1").start();
        new Thread(lockDemo,"窗口2").start();
        new Thread(lockDemo,"窗口3").start();
        new Thread(lockDemo,"窗口4").start();
    }
     @Override
     public void run() {
    
    
        
     }

After completing the above preparations, we can sell tickets.
But, where are the tickets? The conductor is ready at the window, but he doesn’t have a ticket, so he still wants to sell him a hammer?
Insert image description here

public class LockDemo implements Runnable{
    
    

    public static void main(String[] args) {
    
    
        LockDemo lockDemo=new LockDemo();
        new Thread(lockDemo,"窗口1").start();
        new Thread(lockDemo,"窗口2").start();
        new Thread(lockDemo,"窗口3").start();
        new Thread(lockDemo,"窗口4").start();
    }
      private  static  int count =100;
      private Lock lock=new ReentrantLock();

       @Override
       public void run() {
    
    
           while (count>0){
    
    
               sellTickets();
           }
       }

		private void sellTickets() {
    
    
		
		}

Here we provide 100 tickets and prepare a lock. In the run method, we call the ticket selling method. The premise is that tickets can only be sold if there are tickets!

Lock is an interface, which only defines lock, trylock, unlock and other methods, so we look directly at the implementation principle from ReentrentLock. ReentrantLock delegates all Lock interface operations to a Sync class, which inherits AbstractQueuedSynchronizer (AQS for short). Threads using ReentrantLock to acquire locks are divided into two stages. The first stage is the initial competition (ReentrantLock uses unfair locks by default , when we call the lock method of ReentrantLock, it actually calls the lock() of the unfair lock. This method first uses CAS operation to try to seize the lock. If successful, the current thread is set on this lock. Indicates that the preemption is successful. If it fails, LockSupport.park is called to block the current thread, add it to the CLH queue, and wait for preemption). The second stage is based on competition in the CLH queue. (Then it enters the preemption mode of the CLH queue. When the thread holding the lock calls unlock, it will wake up the next node thread of the head node of the CLH queue and call the LockSupport.unpark() method.) In the first competition Whether to consider the queue node directly distinguishes fair locks and unfair locks. In the lock competition based on the CLH queue, CAS operations are relied on to preempt locks, LockSupport is relied on to suspend and wake up threads, and queues are used to ensure that concurrent execution becomes serial execution, thereby eliminating problems caused by concurrency. Generally speaking, ReentrantLock is a relatively lightweight lock, and uses object-oriented thinking to implement the lock function, which is easier to understand than the original synchronized keyword.

For the ticket selling method, we can write it like this, simulate ticket selling, print out the thread name, and add the number of the ticket sold.

 private void sellTickets() {
    
    
                if(count >0){
    
    
                    System.out.println(Thread.currentThread().getName()+",正在出售:"+(100-count+1));
                    count--;
}

Let’s take a look at our running results. After
Insert image description here
trying a few more times ( multi-threaded running results are random ), the situation seems to have turned around. However, the results still appear in clusters... And, what about the lock that I have been talking about? Where's the lock? Woolen cloth?
Insert image description here
Insert image description here
Insert image description here
At this time, you can invite our lock to shine!
Insert image description here

 private void sellTickets() {
    
    
           
            try{
    
    
                lock.lock();//上锁
                if(count >0){
    
    
                    System.out.println(Thread.currentThread().getName()+",正在出售:"+(100-count+1));
                    count--;
                }
            }catch (Exception e){
    
    
                e.getCause();
            }finally {
    
    
                lock.unlock();//释放锁
            }
}

In order to ensure that the lock will be released, I wrote the code to release the lock in the finally block (the code inside will definitely be executed, so my lock will definitely be released)! In order to improve the effect of the program, I made some modifications and added a sleep code to the program:

 private void sellTickets() {
    
    
            try{
    
    
                Thread.sleep(30);
            }catch (Exception e){
    
    
                e.printStackTrace();
            }
            try{
    
    
                lock.lock();//上锁
                if(count >0){
    
    
                    System.out.println(Thread.currentThread().getName()+",正在出售:"+(100-count+1));
                    count--;
                }
            }catch (Exception e){
    
    
                e.getCause();
            }finally {
    
    
                lock.unlock();//释放锁
            }
        }

Please see the final running effect:
Insert image description here

In order to let everyone see the running process clearly, I changed the thread sleep time to 10 seconds...
Please pay attention and observe!
Insert image description here
Insert image description here
Insert image description here
Insert image description here
Insert image description here

The complete source code is as follows:

package cn.uu710;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @version 1.0
 * @author: 张佑
 * @date: 2020-10-09 13:46
 */

public class LockDemo implements Runnable{
    
    

    public static void main(String[] args) {
    
    
        study.study03.LockDemo lockDemo=new study.study03.LockDemo();
        new Thread(lockDemo,"窗口1").start();
        new Thread(lockDemo,"窗口2").start();
        new Thread(lockDemo,"窗口3").start();
        new Thread(lockDemo,"窗口4").start();
    }
    private  static  int count =100;
    private Lock lock=new ReentrantLock();

    @Override
    public void run() {
    
    
        while (count>0){
    
    
            sellTickets();
        }
    }

    private void sellTickets() {
    
    
        try{
    
    
            Thread.sleep(30);
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
        try{
    
    
            lock.lock();//上锁
            if(count >0){
    
    
                System.out.println(Thread.currentThread().getName()+",正在出售:"+(100-count+1));
                count--;
            }
        }catch (Exception e){
    
    
            e.getCause();
        }finally {
    
    
            lock.unlock();//释放锁
        }
    }
}

Insert image description here

Guess you like

Origin blog.csdn.net/YOUYOU0710/article/details/108978392