百木园-与人分享,
就是让自己快乐。

多线程(四)-线程同步

大佬的理解-> Java多线程(三)--synchronized关键字详情

大佬的理解-> Java多线程(三)--synchronized关键字续

1、问题引入

买票问题

1.1 通过继承Thread买票

继承Thread买票案例

/*
    模拟网络购票,多线程资源共享问题,继承Thread方式;
    结论:此种方式,不存在资源共享,通过创建对象启动的线程,每个对象都有各自的属性值
 */
public class MyThreadTicket extends Thread{

    //总票数
    private int remainSite = 100;

    //抢到的座位号
    private int buySite = 0;

    @Override
    public void run() {
        //模拟循环抢票
        while(true){
            //判断余票是否充足,如果不足,结束
            if(remainSite <= 0){
                break;
            }

            //更改强股票数据
            buySite++;
            remainSite--;

            //模拟网络延迟
            try {
                TimeUnit.MILLISECONDS.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName()+\"买到第\"+buySite+\"张票,剩余\"+remainSite+\"张票\");
        }
    }

    public static void main(String[] args) {
        //模拟三人同事抢票
        MyThreadTicket threadTicket1 = new MyThreadTicket();
        threadTicket1.setName(\"猪八戒\");
        MyThreadTicket threadTicket2 = new MyThreadTicket();
        threadTicket2.setName(\"沙和尚\");
        MyThreadTicket threadTicket3 = new MyThreadTicket();
        threadTicket3.setName(\"孙猴子\");

        System.out.println(\"---抢票开始---\");
        threadTicket1.start();
        threadTicket2.start();
        threadTicket3.start();

    }
}

运行结果

---抢票开始---
猪八戒买到第1张票,剩余99张票
孙猴子买到第1张票,剩余99张票
沙和尚买到第1张票,剩余99张票
孙猴子买到第2张票,剩余98张票
猪八戒买到第2张票,剩余98张票
沙和尚买到第2张票,剩余98张票
孙猴子买到第3张票,剩余97张票
沙和尚买到第3张票,剩余97张票
猪八戒买到第3张票,剩余97张票
猪八戒买到第4张票,剩余96张票
沙和尚买到第4张票,剩余96张票
孙猴子买到第4张票,剩余96张票
孙猴子买到第5张票,剩余95张票
......
孙猴子买到第99张票,剩余1张票
猪八戒买到第99张票,剩余1张票
沙和尚买到第99张票,剩余1张票
孙猴子买到第100张票,剩余0张票
猪八戒买到第100张票,剩余0张票
沙和尚买到第100张票,剩余0张票

出现的问题

每个人都买了100张票,没有共享数据;

1.2 通过实现Runnable接口买票

实现Runnable接口案例

/*
    模拟网络购票,实现Runnable方法
 */
public class MyRunnableTicket0 implements Runnable{
    //总票数
    private int remainSite = 100;

    //抢到的座位号
    private int buySite = 0;

    @Override
    public void run() {
        //模拟循环抢票
        while(true){
            //判断余票是否充足,如果不足,结束
            if (remainSite <= 0) {
                break;
            }

            //更改强股票数据
            buySite++;
            remainSite--;

            //模拟网络延迟
            try {
                TimeUnit.MILLISECONDS.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + \"买到第\" + buySite + \"张票,剩余\" + remainSite + \"张票\");
        }

    }

    public static void main(String[] args) {
        //创建三个子线程
        MyRunnableTicket0 runnableTicket = new MyRunnableTicket0();
        Thread thread1 = new Thread(runnableTicket,\"哪吒\");
        Thread thread2 = new Thread(runnableTicket,\"金吒\");
        Thread thread3 = new Thread(runnableTicket,\"木吒\");

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

运行结果

木吒买到第96张票,剩余4张票
哪吒买到第96张票,剩余4张票
金吒买到第96张票,剩余4张票
木吒买到第99张票,剩余1张票
哪吒买到第99张票,剩余1张票
金吒买到第99张票,剩余1张票
木吒买到第100张票,剩余0张票

出现的问题

共享了数据,但是出现了漏票,和几个人买同一张票的情况;

2、解决方法

通过synchronized同步锁来进行同步,使同一时间只有一个人在买票

2.1 同步代码块

同步代码块案例

/*
    模拟网络购票,实现Runnable方法
    同步代码块方法
 */
public class MyRunnableTicket implements Runnable{
    //总票数
    private int remainSite = 100;

    //抢到的座位号
    private int buySite = 0;
    //同步代码块
    @Override
    public void run() {
        //模拟循环抢票
        while(true){
            //同步代码快
            synchronized (this) {
                //判断余票是否充足,如果不足,结束
                if (remainSite <= 0) {
                    break;
                }

                //更改强股票数据
                buySite++;
                remainSite--;

                //模拟网络延迟
                try {
                    TimeUnit.MILLISECONDS.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + \"买到第\" + buySite + \"张票,剩余\" + remainSite + \"张票\");
            }
        }
    }

    public static void main(String[] args) {
        //创建三个子线程
        MyRunnableTicket runnableTicket = new MyRunnableTicket();
        Thread thread1 = new Thread(runnableTicket,\"哪吒\");
        Thread thread2 = new Thread(runnableTicket,\"金吒\");
        Thread thread3 = new Thread(runnableTicket,\"木吒\");

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

运行结果

哪吒买到第1张票,剩余99张票
哪吒买到第2张票,剩余98张票
哪吒买到第3张票,剩余97张票
哪吒买到第4张票,剩余96张票
哪吒买到第5张票,剩余95张票
......
金吒买到第96张票,剩余4张票
金吒买到第97张票,剩余3张票
金吒买到第98张票,剩余2张票
金吒买到第99张票,剩余1张票
金吒买到第100张票,剩余0张票

可以正常买票,问题解决;

2.2 同步方法

同步方法案例

/*
    模拟网络购票,实现Runnable方法
    同步方法
 */
public class MyRunnableTicket implements Runnable{
    //总票数
    private int remainSite = 100;

    //抢到的座位号
    private int buySite = 0;

    @Override
    public void run() {
        //模拟循环抢票
        while(remainSite > 0){

            //调用同步购买方法
            buyTicket();

            //模拟网络延迟
            try {
                TimeUnit.MILLISECONDS.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

    /*
        同步方法
        增加同步锁,限制多线程场景下,只允许一个线程执行当前方法,确保票数修改正确
     */
    public synchronized void buyTicket(){
        //判断余票是否充足,如果不足,结束
        if(remainSite <= 0){
            return;
        }

        //更改强股票数据
        buySite++;
        remainSite--;

        System.out.println(Thread.currentThread().getName()+\"买到第\"+buySite+\"张票,剩余\"+remainSite+\"张票\");
    }

运行结果

哪吒买到第1张票,剩余99张票
哪吒买到第2张票,剩余98张票
哪吒买到第3张票,剩余97张票
哪吒买到第4张票,剩余96张票
哪吒买到第5张票,剩余95张票
......
金吒买到第96张票,剩余4张票
金吒买到第97张票,剩余3张票
金吒买到第98张票,剩余2张票
金吒买到第99张票,剩余1张票

可以正常买票,问题解决;


来源:https://www.cnblogs.com/xiaoqigui/p/16396916.html
本站部分图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » 多线程(四)-线程同步

相关推荐

  • 暂无文章