0
点赞
收藏
分享

微信扫一扫

Java多线程—同步代码块问题解决方法


目录

​​一、问题案例​​

​​二、解决方法​​

​​三、原因分析​​

一、问题案例

某电影院共有100张票,而它有3个窗口卖票,设计一个程序模拟电影院卖票

问题:同一窗口卖完所有的票

代码:

public class SellTicket implements Runnable {
private int tickets = 100;
private Object obj = new Object();

@Override
public void run() {
while (true) {
synchronized (obj) {
if (tickets > 0) {
//通过sleep来模拟出票时间
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
}
}

测试类:

public class SellTicketDemo {
public static void main(String[] args) {
//创建SellTicket类的对象
SellTicket st = new SellTicket();

//创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
Thread t1 = new Thread(st,"窗口1");
Thread t2 = new Thread(st,"窗口2");
Thread t3 = new Thread(st,"窗口3");

//启动线程
t1.start();
t2.start();
t3.start();
}
}

运行结果:

Java多线程—同步代码块问题解决方法_开发语言

二、解决方法

 把模拟出票时间放到同步代码块外面,就能看见3个窗口在同时卖票。

代码:

public class SellTicket implements Runnable {
private int tickets = 100;
private Object obj = new Object();

@Override
public void run() {
while (true) {
//通过sleep来模拟出票时间
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj) {
if (tickets1 > 0) {
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
}
}

运行结果:

Java多线程—同步代码块问题解决方法_后端_02

三、原因分析

在第一个的运行结果中,窗口1进入Runnable(可运行状态),很明显是窗口1线抢到了持有锁,此时,尝试获取锁,窗口1成功拿到锁并执行程序进行卖票;

而在窗口1之后启动的窗口2和3在启动之后也尝试去获取锁,发现锁已经被别人拿走了,于是进入锁池(注意:在同步状态下,没有获取到锁的会进入到等待池,锁池会比等待池中的其他线程更优先于去获取锁);

在窗口1卖完1张票之后,开始释放锁,此时,窗口2和3同时发现锁空了,正准备上去抢,结果窗口1发现自己又需要锁了,于是再次获取锁,窗口1一直围绕在锁的旁边,而窗口2和3在锁池中的板凳上(等待池)上坐着,肯定没有窗口1抢的快。

所以就造成了同一窗口一直卖票的情况。

 

举报

相关推荐

0 条评论