线程同步第四[自学笔记,大神绕路]

线程同步问题

写一个模拟买票的程序

class Sell implements Runnable {
    private int ticket = 3;
    @Override
    public void run() {
        while(true){
            if(this.ticket > 0){
                System.out.println("【" + Thread.currentThread().getName() 
                        + "卖出的第" + ticket-- + "张票】");
            } else {
                break;
            }
        }
    }
}

public class Windows {
    public static void main(String[] args) {
        Sell sell1 = new Sell();

        Thread thread1 = new Thread(sell1,"窗口A");
        Thread thread2 = new Thread(sell1,"窗口B");
        Thread thread3 = new Thread(sell1,"窗口C");

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

随机抽取其中的依次执行结果。
在这里插入图片描述
对于这种数据出现问题的情况,我们称为线程不同步。


对于线程不同步,我们可以采取一种有味道的方法来理解。
A和B同时去上厕所,并且这个厕所每次只能容纳一个人去方便;当A进去的时候,还没来得及蹲下,B就进来了,这时候就出现了一个马桶上承受着两个人的情况,这就会必然导致有一个人的排泄物出现在马桶外面的情况。这就对应着卖出第0张票的情况。
为了解决这个上厕所的问题,我们可以在厕所的门上设计一把锁,当A进入之后,先把门锁上,这时无论A在里面多久,无论蹲没蹲下,B都无法进入。这样就可以保证不会出现意外了。


因此为了线程同步,我们需要在代码上加一把所,这个锁就是synchronized。

同步代码块

我们把使数据发生变化的那段代码放入synchronized关键字定义的代码块中,就可以实现线程同步。
在这段代码中,对数据操作的代码是if语句,因此我们将if语句放在synchronized代码块中。

class Sell implements Runnable {
    private int ticket = 3;

    @Override
    public void run() {
        while (true) {
            /*
            在synchronized代码块执行的时候需要指定一个设置同步的
            对象,显然操作的对象就是本对象,因此我们使用this
            */
            synchronized (this) {
                if (this.ticket > 0) {
                    System.out.println("【" + Thread.currentThread().getName()
                            + "卖出的第" + ticket-- + "张票】");
                } else {
                    break;
                }
            }
        }
    }
}

public class Windows {
    public static void main(String[] args) {
        Sell sell1 = new Sell();

        Thread thread1 = new Thread(sell1, "窗口A");
        Thread thread2 = new Thread(sell1, "窗口B");
        Thread thread3 = new Thread(sell1, "窗口C");

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

随机取其中的一次执行结果。
在这里插入图片描述

同步方法

直接将synchronized加在对数据操作的方法上,实现线程同步。

class Sell implements Runnable {
    private int ticket = 3;

    @Override
    public synchronized void run() {
        while (true) {
            if (this.ticket > 0) {
                System.out.println("【" + Thread.currentThread().getName()
                        + "卖出的第" + ticket-- + "张票】");
            } else {
                break;
            }
        }
    }
}

public class Windows {
    public static void main(String[] args) {
        Sell sell1 = new Sell();

        Thread thread1 = new Thread(sell1, "窗口A");
        Thread thread2 = new Thread(sell1, "窗口B");
        Thread thread3 = new Thread(sell1, "窗口C");

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

但是一旦涉及了同步,就意味着性能的下降。

发布了34 篇原创文章 · 获赞 27 · 访问量 5839

猜你喜欢

转载自blog.csdn.net/weixin_46192593/article/details/105317113