欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于synchronized和ReentrantLock实现卖票功能以及synchronized的对象锁和全局锁验证

程序员文章站 2022-03-06 22:47:15
...

采用synchronize关键字实现卖票
package com.huang.thread;

/**
 * 卖票
 * 使用synchronize关键字实现
 * @author 黄
 *
 */
public class TicketSynch implements Runnable {

 private int ticketCount;
 
 public TicketSynch(int ticketCount) {
  this.ticketCount = ticketCount;
 }
 
 public void sell() {
  while(true) {
   synchronized (this) {
    if(ticketCount > 0) {
     try {
      //模拟买票的动作
      Thread.sleep(100);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     ticketCount --;
     System.out.println(Thread.currentThread().getName() + "卖出一张票:剩余票数" + ticketCount);
    }else {
     System.exit(0);
    }
   }
  }
 }
 
 @Override
 public void run() {
  sell();
  
 }

}


采用Reentrantlock关键字实现卖票

package com.huang.thread;

import java.util.concurrent.locks.ReentrantLock;

/**
 * 卖票
 * 使用Reentrantlock 重入锁控制
 * @author 黄
 *
 */
public class TicketLock implements Runnable {
 
 private int ticketCount;
 
 private ReentrantLock lock = new ReentrantLock();
 
 public TicketLock(int ticketCount) {
  this.ticketCount = ticketCount;
 }
 
 public void sell() {
  while(true) {
   try {
    lock.lock();
    if(ticketCount > 0) {
     try {
      //模拟买票的动作
      Thread.sleep(100);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     ticketCount --;
     System.out.println(Thread.currentThread().getName() + "卖出一张票:剩余票数" + ticketCount);
    }else {
     System.exit(0);
    }
   }catch (Exception e) {
    e.printStackTrace();
   }finally {
    lock.unlock();
   }
  }
 }
 
 @Override
 public void run() {
  sell();
 }

}

 

测试类

package com.huang.thread;

import org.junit.jupiter.api.Test;

public class TestTicket {
 
 @Test
 public void testSynch() {
  TicketSynch ticketSynch = new TicketSynch(100);
  //这里调用synchronized (this)同步锁对象的方法。这里输出的对象和this是同一个对象
  //System.out.println(ticketSynch);
  
  new Thread(ticketSynch,"窗口1").start();
  new Thread(ticketSynch,"窗口2").start();
  new Thread(ticketSynch,"窗口3").start();
  new Thread(ticketSynch,"窗口4").start();
  new Thread(ticketSynch,"窗口5").start();
  
  try {
   //主线程等到30秒,等待其他线程执行完成
   Thread.sleep(30*1000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }
 
 @Test
 public void testLock() {
  TicketLock ticketSynch = new TicketLock(100);
  
  new Thread(ticketSynch,"窗口1").start();
  new Thread(ticketSynch,"窗口2").start();
  new Thread(ticketSynch,"窗口3").start();
  new Thread(ticketSynch,"窗口4").start();
  new Thread(ticketSynch,"窗口5").start();
  
  try {
   //主线程等到30秒,等待其他线程执行完成
   Thread.sleep(30*1000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }
 
 /**
  * 测试Synchronize关键字的全局锁和对象锁
  */
 @Test
 public void testSynchLock() {
  TicketSynchLock ticketSynch = new TicketSynchLock();
  new Thread(ticketSynch,"窗口1").start();
  new Thread(ticketSynch,"窗口2").start();
  new Thread(ticketSynch,"窗口3").start();
  TicketSynchLock ticketSynch1 = new TicketSynchLock();
  new Thread(ticketSynch1,"窗口3").start();
  new Thread(ticketSynch1,"窗口4").start();
  
  try {
   //主线程等到30秒,等待其他线程执行完成
   Thread.sleep(30*1000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }

}

synchronized的对象锁和全局锁验证,重新写一下类

package com.huang.thread;

/**
 * 卖票
 * 使用synchronize关键字实现
 * @author 黄
 *
 */
public class TicketSynchLock implements Runnable {

 private static int ticketCount = 100;
 
 /**
  * 对象锁
  */
 public void sell() {
  while(true) {
   synchronized (this) {
    if(ticketCount > 0) {
     try {
      //模拟买票的动作
      Thread.sleep(100);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     ticketCount --;
     System.out.println(Thread.currentThread().getName() + "卖出一张票:剩余票数" + ticketCount);
    }else {
     return;
    }
   }
  }
 }
 
 /**
  * 全局锁
  */
 public void sell1() {
  while(true) {
   synchronized (TicketSynchLock.class) {
    if(ticketCount > 0) {
     try {
      //模拟买票的动作
      Thread.sleep(100);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     ticketCount --;
     System.out.println(Thread.currentThread().getName() + "卖出一张票:剩余票数" + ticketCount);
    }else {
     return;
    }
   }
  }
 }
 
 @Override
 public void run() {
  //sell();
  sell1();
  
 }

}


测试,上面测试类的testSynchLock()方法,当TicketSynchLock类run方法执行的是sell()的时候,则会出现-1张票,如果执行sell1(),则不会

借鉴网上博客的描述:

synchronized 作用在普通方法上属于对象锁,作用在静态方法,类.class 上面,属于全局锁。对象锁只对同一个对象加锁,作用对象是同一个对象。而类锁是对类加锁,对整个类都有效。
如果锁住的是一般方法就是对象锁,对象锁只会对同一个对象起作用,如果是锁住了static 方法则是全局锁,会对全局对象都管用,如果想在普通方法中使用全局锁需要锁住class对象。

 

 

相关标签: thread