关于synchronized和ReentrantLock实现卖票功能以及synchronized的对象锁和全局锁验证
采用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对象。
上一篇: html怎么设置不换行
下一篇: php如何破解禁止跨域访问