运行代码:
public static void main(String[] args) {
SellTicket st = new 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();
}
Demo1:
package course;
/**
* 买票窗口
*/
public class SellTicket implements Runnable {
private int tickets = 10;
@Override
public void run() {
int sum = 10;
while (true){
if (tickets > 0) {
tickets--;
System.out.println(Thread.currentThread().getName() + "正在出售第" + (sum - tickets) + "张票");
}
}
}
}
线程安全问题
运行以上代码,3个售票窗口售卖10张票会出现超卖或少卖的情况
为什么会出现问题?(这也是我们判断多线程程序是否会有数据安全问题的标准)
- 是否是多线程环境
- 是否有共享数据
- 是否有多条语句操作共享数据
如何解决多线程按问题?
- 让程序没有安全问题的环境
- 实现方式:把多条语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可
解决方法:
同步代码块:锁多条语句操作共享数据,可以使用同步代码块
格式:
synchronized(任意对象){多条语句操作共享数据的代码
}
- 通过Lock类
Demo2(修改Demo1,使用synchronized关键字):
package course;
/**
* 买票窗口
*/
public class SellTicket implements Runnable {
private int tickets = 10;
//使用同步代码块
private Object obj = new Object();
@Override
public void run() {
int sum = 10;
synchronized (obj) {
while (true) {
if (tickets > 0) {
tickets--;
System.out.println(Thread.currentThread().getName() + "正在出售第" +(sum - tickets)+ "张票");
}
}
}
}
}
Demo3(修改Demo2,使用Lock类):
package course;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 买票窗口
*/
public class SellTicket implements Runnable {
private int tickets = 10;
//使用Lock 通过Lock的实现类
private Lock lock = new ReentrantLock();
@Override
public void run() {
int sum = 10;
while (true) {
lock.lock();
if (tickets > 0) {
tickets--;
System.out.println(Thread.currentThread().getName() + "正在出售第" +(sum - tickets)+ "张票");
}
lock.unlock();
}
}
}