补充:
同步:线程任务一个接着一个的有序进行 - 比如:坐地铁检票,试衣间试衣服 —- 线程安全
异步:多个线程同时进行,谁抢到就是谁的 - 比如:一群人上卡车 —- 线程不安全
最终的方案:将异步转化为同步!
在Java中使用synchronized关键字来解决,将一套完整的动作使用synchronized包裹
同步代码块:
synchronized(锁对象){
可能出现线程安全问题的代码
}
同步代码块中的锁对象可以实任意的对象,但是保证多个线程操作相同的数据的时候,要使用同一个锁才能保证线程的安全
同步的解决方案的解释:
- 线程A操作数据的代码与线程B操作的数据的代码均使用synchronized包裹,并使用对象锁
- 线程A进入绒布块进行数据操作的时候,线程B只能等待线程A操作结束以后才进入同步代码块继续执行
- 反之就是线程A等待线程B,两个交替运行
对象锁
package Test22_Demo.Demo04;/*
@create 2020--12--15--10:32
*/
/**
* 使用第二种方式创建线程,原因是执行线程目标对象共享
* 顶一个卖票的线程执行目标对象 - 加锁
*
*/
public class Ticket implements Runnable {
//票数
private int number = 100;
//生命成员变量为定义锁对象
private Object lock = new Object();
@Override
public void run() {
while (true) {
synchronized (lock) {
//线程暂停
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//如果有票就卖
if (number > 0) {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + "正在销售第"+(number--) + "张票");
} else {
//没票了
break;
}
}
}
}
}
package Test22_Demo.Demo04;/*
@create 2020--12--15--10:44
*/
import Test22_Demo.Demo04.Ticket;
/**
* 测试线程
*/
public class ThreadDemo {
public static void main(String[] args) {
//实例化目标
Ticket ticket = new Ticket();
//使用该买票的目标创建多个程序
Thread thread1 = new Thread(ticket, "Jack");
Thread thread2 = new Thread(ticket, "Rose");
Thread thread3 = new Thread(ticket, "Tom");
//启动多个线程
thread1.start();
thread2.start();
thread3.start();
}
}