Java 多线程编程--线程同步一(synchronized)

341 阅读3分钟

线程原始状态是不同步的

    java的多线程启动后,在没有使用锁的情况下,会各自执行各自的代码,而不管其它线程运行状态。这种情况下,当多个线程使用同一个变量,就会出现数据混乱。(这也就是对线程不安全的理解)

    下面看一个例子: 以销售火车票为例,总共有100张火车票,同时开设两个售票窗口进行售票。

    对于这个例子,我们把100张火车票抽象为一个整形变量--ticket,值为100。两个售票窗口抽象为两个子线程,在子线程中进行ticket的自减,就是售票行为。

线程不同步

package ticket;

public class Main {
    public static void main(String[] args) {
        int ticket=100;
        Window window1=new Window(ticket);
        window1.setName("窗口1");
        Window window2=new Window(ticket);
        window2.setName("窗口2");

        window1.start();
        window2.start();
    }
}

class Window extends Thread{
    private int ticket;

    public Window( int ticket) {
        this.ticket = ticket;
    }

    @Override
    public void run(){
        String windowName=Thread.currentThread().getName();
        while(ticket>0){
            ticket--;
            System.out.println(windowName+"卖出一张票            剩余票数"+ticket);

        }

    }
}

    运行结果:

取部分结果:
窗口2卖出一张票            剩余票数5
窗口2卖出一张票            剩余票数4
窗口2卖出一张票            剩余票数3
窗口2卖出一张票            剩余票数2
窗口2卖出一张票            剩余票数1
窗口2卖出一张票            剩余票数0
窗口1卖出一张票            剩余票数20

    可以看到,窗口2已经把票卖完了,而窗口1还显示拥有20张票,这就是因为线程不同步,导致线程间共享数据不一致。

线程同步

package ticket;

public class Main {
    public static void main(String[] args) {
        Ticket ticket =new Ticket();
        ticket.count=100;
        Window window1=new Window(ticket);
        window1.setName("窗口1");
        Window window2=new Window(ticket);
        window2.setName("窗口2");

        window1.start();
        window2.start();
    }
}

class Window extends Thread{
    private Ticket ticket;

    public Window( Ticket ticket) {
        this.ticket = ticket;
    }

    @Override
    public void run(){
        String windowName=Thread.currentThread().getName();
        while(ticket.count>0){
            synchronized (ticket) {
                ticket.count--;
                System.out.println(windowName + "卖出一张票            剩余票数" + ticket.count);
            }
        }

    }
}

class Ticket {
    int count;
}
取部分结果:
窗口1卖出一张票            剩余票数99
窗口1卖出一张票            剩余票数98
窗口1卖出一张票            剩余票数97
窗口1卖出一张票            剩余票数96
窗口1卖出一张票            剩余票数95
窗口1卖出一张票            剩余票数94
窗口1卖出一张票            剩余票数93
窗口1卖出一张票            剩余票数92
窗口1卖出一张票            剩余票数91
窗口1卖出一张票            剩余票数90
窗口1卖出一张票            剩余票数89
窗口1卖出一张票            剩余票数88
窗口1卖出一张票            剩余票数87
窗口1卖出一张票            剩余票数86
窗口1卖出一张票            剩余票数85
窗口1卖出一张票            剩余票数84
窗口1卖出一张票            剩余票数83
窗口2卖出一张票            剩余票数82
窗口2卖出一张票            剩余票数81
窗口2卖出一张票            剩余票数80
窗口2卖出一张票            剩余票数79
窗口2卖出一张票            剩余票数78

    可以看到,加上线程同步后,窗口1和窗口2实现了票数的共享,票数在逐一的减少。

    关于线程同步的具体方式,见下一章节。

    ps:该同步代码有一个问题,大家可以运行代码后想想看问题在哪里以及怎么解决(该问题恰好反应在多线程编程中,你觉得是这样,可实际不是这样)

有任何问题、意见请在下面留言或者邮箱联系-310103270@qq.com