一、什么是线程同步?
通俗的讲就是多个线程操作同一个资源
二、线程同步的形成条件
队列 + 锁 (每个对象都有一把锁)
三、了解线程同步锁
![](https://i-blog.csdnimg.cn/blog_migrate/caa60777223e4552f3eba0a64703db29.png)
1、使用synchronized关键字同步方法
public class UnsafeBuyTicket {
public static void main(String[] args) {
ByTicket station = new ByTicket();
//创建多个线程
new Thread(station,"张三").start();
new Thread(station,"李四").start();
new Thread(station,"王五").start();
}
}
class ByTicket implements Runnable{
//定义票数
private int ticketNum = 10;
//手动设置停止
boolean flag = true;
@Override
public void run() {
//买票
while (flag){
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//解决线程同步问题,增加synchronized关键字,将方法变成同步方法即可
private synchronized void buy() throws InterruptedException {
//判断是否有票
/*
* 最后运行结果为什么会有0和-1?
* 因为当还剩下最后一张票的时候,三个线程都会觉得还有票,就会按照优先级拿到那一张票,然后执行ticketNum--的方法,
* 线程具有并发性,所以他们还会继续执行买票的方法,所以就会出现负数和0(程序不像人类知道自动排队)
* */
if (ticketNum <= 0){
flag = false;
return;
}
//手动设置延时
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + "买到了第" + ticketNum-- + "张票");
}
}
2、使用synchronized关键字,同步代码块
(1)锁对象
![](https://i-blog.csdnimg.cn/blog_migrate/e5d4cfdfcff7924280496d48e041001a.png)
(2)锁集合
![](https://i-blog.csdnimg.cn/blog_migrate/bfe657cf81a60df23802185099b256f9.png)
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/889cf847fbb8b39114cdd783590b2991.png)