Thread synchronization and use of locks

Why thread locks are needed

Assuming that there are three threads selling 100 tickets at the same time, we know that a ticket can only be sold once. If thread locks are not used, a ticket may be sold three times by three threads at the same time.
Next, use the program to demonstrate

package com.test.lock;

public class SellTicket3 implements Runnable {
    
    
	
	private static int tickets=100;
	
	
	public void run()
	{
    
    
		 while(true)
		 {
    
    
			 
			 
			 //隐士锁 内置锁 方式1 锁住代码块
			
				 if(tickets>0)
				 {
    
    				 
					 System.out.println(Thread.currentThread().getName()+"售出第..."+tickets+"...张票");
					 
					 tickets--;
					 
					 try {
    
    
						Thread.sleep(10); //休眠 10毫秒
					} catch (InterruptedException e) {
    
    
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					 
				 } 
		 }
		
	}

}

package com.test.lock;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test2 {
    
    

	/**
	 * @param args
	 */
	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub

		//创建线程池对象
		 ExecutorService pool= Executors.newFixedThreadPool(3);
		 
		 //创建售票任务 对象
		 SellTicket3 sellTicket=new SellTicket3();
		 
		 pool.submit(sellTicket);
		 
		 pool.submit(sellTicket);
		 
		 pool.submit(sellTicket);
		
		
	}

}

Observing the console input, the 100th ticket is sold three times, which is problematic.
insert image description here

Use thread locks to solve this problem

There are two ways to create thread locks, implicit locks and explicit locks.

implicit lock

package com.test.lock;

public class SellTicket implements Runnable {
    
    
	
	private static int tickets=100;
	
	
	public void run()
	{
    
    
		 while(true)
		 {
    
    
			 
			 
			 //隐士锁 内置锁 方式1 锁住代码块
			 synchronized (this) {
    
    				
			
				 if(tickets>0)
				 {
    
    				 
					 System.out.println(Thread.currentThread().getName()+"售出第..."+tickets+"...张票");
					 
					 tickets--;
					 
					 try {
    
    
						Thread.sleep(10); //休眠 10毫秒
					} catch (InterruptedException e) {
    
    
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					 
				 }
				
			 }
		 
		 }
		
	}

}

package com.test.lock;

public class SellTicket implements Runnable {
    
    
	
	private static int tickets=100;
	
	
	public void run()
	{
    
    
		 while(true)
		 {
    
    
			 
			 
			//方式 2
			 sellTicket();  
			 
			 
			 
			 
		 }
		
	}
	
	//方式2 锁住方法(成员方法或静态方法)
	public synchronized void sellTicket()
	{
    
    		
		 if(tickets>0)
		 {
    
    				 
			 System.out.println(Thread.currentThread().getName()+"售出第..."+tickets+"...张票");
			 
			 tickets--;
			 
			 try {
    
    
				Thread.sleep(10); //休眠 10毫秒
			} catch (InterruptedException e) {
    
    
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			 
		 }
	}
	

}

show lock

package com.test.lock;

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

public class SellTicket2 implements Runnable {
    
    

	private static int tickets=100;
	
	//显示锁
	private Lock lock=new ReentrantLock();
	
	
	@Override
	public void run() {
    
    
		// TODO Auto-generated method stub
		
		while(true)
		{
    
    
			lock.lock(); //上锁
			
			//lock.tryLock(arg0, arg1)//设置等待的时间的
			if(tickets>0)
			{
    
    
				System.out.println(Thread.currentThread().getName()+"售出第.."+tickets+"..张票");
				
				tickets--;
				
				try {
    
    
					Thread.sleep(10);
				} catch (InterruptedException e) {
    
    
					// TODO Auto-generated catch block
					e.printStackTrace();
				}				
			}			
			//开锁
			lock.unlock(); 
			
		}
		
	}
	
	

}

run test

package com.test.lock;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
    
    

	/**
	 * @param args
	 */
	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub

		//创建线程池对象
		 ExecutorService pool= Executors.newFixedThreadPool(3);
		 
		 //创建售票任务 对象
		 SellTicket2 sellTicket=new SellTicket2();
		 
		 pool.submit(sellTicket);
		 
		 pool.submit(sellTicket);
		 
		 pool.submit(sellTicket);
		
		
	}

}

There is no case where the same ticket is sold multiple times
insert image description here

How to choose between implicit and explicit locks

More parameters can be set using explicit locks, such as waiting time.
If an implicit lock is used, if the code in the thread is abnormal, it will cause a deadlock. At this time, using an explicit lock to set the waiting time can avoid the deadlock situation.

Guess you like

Origin blog.csdn.net/Rockandrollman/article/details/130470304