同步代码块

package com.shujia.day19.sellTickets3;

/*
    使用Runnable的方式实现

    为了模拟更加真实的售票情况,我们加入延迟
    问题:
        我们加入了延迟之后,发现
        a. 有重复售卖同一张票的情况(原因1)
        b. 还出现了一个不该出现的票数据,比如第0张票,第-1张票(原因2)
    原因:
        1. cpu小小的时间片,足以让程序执行很多次
        2. 线程的执行具有随机性,且是抢占式执行的

    现象:线程不安全的现象
        如何判断一个程序是否存在线程不安全的现象呢?
        三要素(同时满足):
            1、是否存在多线程环境?
            2、是否存在共享数据?
            3、是否存在多条语句操作着共享数据?
    如何解决线程不安全的现象?
        1、同步代码块
        2、lock锁

    解决方案1:加入同步代码块
        synchronized(对象){
            操作共享数据的代码
        }
      这里的对象,可以是任意一个new出来的对象,但是要保证多个线程之间是同一个对象。

    synchronized的使用:
        1、同步代码块 - 锁对象 - 任意一个对象,前提是多个线程对象共享一个
        2、同步方法 - 锁对象 - this
        3、同静态方法 - 锁对象 - 当前类的class文件对象


    解决方案2:lock锁


 */
class Window implements Runnable {
    private static int tickets = 100;
//    private Object object = new Object();
    private int i = 0;


    @Override
    public void run() {
        while (true) {
            if (i % 2 == 0) {
                synchronized (Window.class) {
                    if (tickets > 0) {
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + " 正在出售第 " + (tickets--) + " 张票......");
                    }
                }
            } else {
                sellTicket();
            }

            i++;
        }
    }

    //同步方法,将synchronized在方法定义上出现
//    public synchronized void sellTicket() {
//        if (tickets > 0) {
//            try {
//                Thread.sleep(50);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println(Thread.currentThread().getName() + " 正在出售第 " + (tickets--) + " 张票......");
//        }
//    }


    public static synchronized void sellTicket() {
        if (tickets > 0) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 正在出售第 " + (tickets--) + " 张票......");
        }
    }
}

public class SellTicketDemo1 {
    public static void main(String[] args) {
        Window window = new Window();

        Thread w1 = new Thread(window, "窗口1");
        Thread w2 = new Thread(window, "窗口2");
        Thread w3 = new Thread(window, "窗口3");

        w1.start();
        w2.start();
        w3.start();

    }
}
posted @ 2024-08-19 22:11  ていせい  阅读(23)  评论(0)    收藏  举报