JavaAdv——多线程同步案例(售票系统)
售票系统
假设您正在开发一个基于Java多线程技术的售票系统。该系统需要支持多个售票窗口同时进行售票操作,并且要确保不会出现超卖或漏卖的情况。具体来说,系统应该具备如下特点:
-
票的数量有限:初始时系统中有100张票。
-
多线程售票:系统支持多个售票窗口同时进行售票操作。
-
线程安全:必须确保即使在高并发情况下也不会出现超卖或漏卖的问题。
Runnable
==查看结果,分析代码==
public void run() {
while (true) {
if (count > 0) {
System.out.println(Thread.currentThread().getName() + "正在卖第" + count + "张票");
count--;
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
} else {
break;
}
}
}
==加上同步锁==
public void run() {
while (true) {
synchronized (this) {
if (count > 0) {
System.out.println(Thread.currentThread().getName() + "正在卖第" + count + "张票");
count--;
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
} else {
break;
}
}
}
}
==注意同步锁的位置==
public void run() {
while (count > 0) {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + "正在卖第" + count + "张票");
count--;
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Thread
public class TicketOffice {
private Integer count = 100;
public synchronized Integer getCount() {
return count;
}
public synchronized void sell() {
if (count > 0) {
count--;
System.out.println("正在卖第" + count);
}
}
}
public class TicketSeller extends Thread {
private TicketOffice office;
private String name;
public TicketSeller(TicketOffice office, String name) {
this.office = office;
this.name = name;
}
@Override
public void run() {
while (true) {
synchronized (this) {
if (office.getCount() > 0) {
try {
office.sell();
Thread.sleep(100); // 模拟售票延迟
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
}
}
}
==在synchronized
块内的操作,确实是在该块执行完毕前不会被其他线程打断的。==
==但是,如果在这个同步块内调用了某个非同步的方法,并且这个方法修改了共享资源,那么就有可能会出现线程安全问题。==
synchronized
块的作用范围
在一个代码块上使用synchronized
关键字时,该块内的所有操作都会被视为原子的,在该块内不会被其他线程打断。
然而,这种保证仅限于该同步块内。如果在同步块内调用了一个非同步的方法,那么该方法的操作就不受该同步块的保护,可能会被其他线程干扰。