补充:
    同步:线程任务一个接着一个的有序进行 - 比如:坐地铁检票,试衣间试衣服 —- 线程安全
    异步:多个线程同时进行,谁抢到就是谁的 - 比如:一群人上卡车 —- 线程不安全

    最终的方案:将异步转化为同步!

    在Java中使用synchronized关键字来解决,将一套完整的动作使用synchronized包裹

    同步代码块:
    synchronized(锁对象){
    可能出现线程安全问题的代码
    }
    同步代码块中的锁对象可以实任意的对象,但是保证多个线程操作相同的数据的时候,要使用同一个锁才能保证线程的安全

    同步的解决方案的解释:

    1. 线程A操作数据的代码与线程B操作的数据的代码均使用synchronized包裹,并使用对象锁
    2. 线程A进入绒布块进行数据操作的时候,线程B只能等待线程A操作结束以后才进入同步代码块继续执行
    3. 反之就是线程A等待线程B,两个交替运行

    对象锁

    1. package Test22_Demo.Demo04;/*
    2. @create 2020--12--15--10:32
    3. */
    4. /**
    5. * 使用第二种方式创建线程,原因是执行线程目标对象共享
    6. * 顶一个卖票的线程执行目标对象 - 加锁
    7. *
    8. */
    9. public class Ticket implements Runnable {
    10. //票数
    11. private int number = 100;
    12. //生命成员变量为定义锁对象
    13. private Object lock = new Object();
    14. @Override
    15. public void run() {
    16. while (true) {
    17. synchronized (lock) {
    18. //线程暂停
    19. try {
    20. Thread.sleep(500);
    21. } catch (InterruptedException e) {
    22. e.printStackTrace();
    23. }
    24. //如果有票就卖
    25. if (number > 0) {
    26. String threadName = Thread.currentThread().getName();
    27. System.out.println(threadName + "正在销售第"+(number--) + "张票");
    28. } else {
    29. //没票了
    30. break;
    31. }
    32. }
    33. }
    34. }
    35. }
    1. package Test22_Demo.Demo04;/*
    2. @create 2020--12--15--10:44
    3. */
    4. import Test22_Demo.Demo04.Ticket;
    5. /**
    6. * 测试线程
    7. */
    8. public class ThreadDemo {
    9. public static void main(String[] args) {
    10. //实例化目标
    11. Ticket ticket = new Ticket();
    12. //使用该买票的目标创建多个程序
    13. Thread thread1 = new Thread(ticket, "Jack");
    14. Thread thread2 = new Thread(ticket, "Rose");
    15. Thread thread3 = new Thread(ticket, "Tom");
    16. //启动多个线程
    17. thread1.start();
    18. thread2.start();
    19. thread3.start();
    20. }
    21. }