线程同步的思路
有时线程之间彼此不独立, 需要同步
1, 线程间的互斥
同时运行的几个线程需要共享 一个(些) 数据
共享的数据, 在某一时刻只允许一个线程对其进行操作
2, "生产者/消费者" 问题
假设有一个线程负责往 数据区 写数据, 另一个线程从 同一数据区中 读数据, 两个线程可以并行执行
如果数据区已满, 生产者要等 消费者 取走一些数据后, 才能再写
当数据区空时, 消费者要等生产者写入一些数据后, 再取
用两个线程模拟 存票, 售票过程
假定开始售票处, 并没有票, 一个线程往里面存票. 另外一个线程则往外 卖票
我们新建一个 票类对象, 让 存票 和 售票 线程 都访问它,
本例采用2个线程, 共享同一数据对象, 来实现对 同一份数据的操作
public class ProducerAndConsumer {
public static void main(String[] args) {
Tickets t = new Tickets(10); // 建立票对象, 票总数10
new Consumer(t).start(); // 开始卖票线程
new Producer(t).start(); // 开始存票线程
}
}
class Tickets {
int number = 0; // 票号
int size; // 总票数
boolean available = false; // 表示目前是否有票可售
public Tickets(int size) { // 构造方法, 传入总票数参数
this.size = size;
}
}
线程间的互斥
class Producer extends Thread {
Ticket t = null;
public Producer(Tickets t) {
this.t = t;
}
public void run() {
while (t.number < t.size) {
System.out.println("Producer puts ticket " + (++t.number));
t.available = true;
}
}
}
class Consumer extends Thread {
Tickets t = null;
int i = 0;
public Consumer(Tickets t) {
this.t = t;
}
public void run() {
while (i < t.size) {
if (t.availabe == true && i <= t.number) {
System.out.println("Consumer buys ticket " + (++i));
}
if (i == t.number) {
t.available = false;
}
}
}
}
如果我们在 t.available = false 之前 加上 sleep语句, 让售票线程 多停留一会
if (i == t.number) {
try {
Thread.sleep(1);
} catch (InterruptedException exception) {
};
t.available = false;
}
则会出现错误
原因 是 票线程运行到 t.available = false 之前, 休眠 1ms
导致 cpu 切换到 存票线程, 将 available 置为 true, 直到整个存票线程结束
此时, 再次切换到 售票线程
- 执行 t.available = false, 此时 售票号 小于 存票号, 且 存票线程已经结束 不再能将 t.available 置为 true, 则 售票线程陷入了 死循环
参考链接
https://www.xuetangx.com/learn/THU08091000252/THU08091000252/7754101/video/12732930