JavaAdv——多线程同步案例(售票系统)

售票系统

假设您正在开发一个基于Java多线程技术的售票系统。该系统需要支持多个售票窗口同时进行售票操作,并且要确保不会出现超卖或漏卖的情况。具体来说,系统应该具备如下特点:

  1. 票的数量有限:初始时系统中有100张票。

  2. 多线程售票:系统支持多个售票窗口同时进行售票操作。

  3. 线程安全:必须确保即使在高并发情况下也不会出现超卖或漏卖的问题。

Runnable

==查看结果,分析代码==

public void run() {
    while (true) {
        if (count > 0) {
            System.out.println(Thread.currentThread().getName() + "正在卖第" + count + "张票");
            count--;
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            break;
        }
    }
}

==加上同步锁==

public void run() {
    while (true) {
        synchronized (this) {
            if (count > 0) {
                System.out.println(Thread.currentThread().getName() + "正在卖第" + count + "张票");
                count--;
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                break;
            }
        }
    }
}

==注意同步锁的位置==

public void run() {
    while (count > 0) {
        synchronized (this) {
            System.out.println(Thread.currentThread().getName() + "正在卖第" + count + "张票");
            count--;
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Thread

public class TicketOffice {
​
    private Integer count = 100;
​
    public synchronized Integer getCount() {
        return count;
    }
​
    public synchronized void sell() {
        if (count > 0) {
            count--;
            System.out.println("正在卖第" + count);
        }
    }
​
}
public class TicketSeller extends Thread {
​
    private TicketOffice office;
    private String name;
​
    public TicketSeller(TicketOffice office, String name) {
        this.office = office;
        this.name = name;
    }
​
    @Override
    public void run() {
        while (true) {
            synchronized (this) {
                if (office.getCount() > 0) {
                    try {
                        office.sell();
                        Thread.sleep(100); // 模拟售票延迟
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    break;
                }
            }
        }
    }
​
}

==在synchronized块内的操作,确实是在该块执行完毕前不会被其他线程打断的。==

==但是,如果在这个同步块内调用了某个非同步的方法,并且这个方法修改了共享资源,那么就有可能会出现线程安全问题。==

synchronized块的作用范围

在一个代码块上使用synchronized关键字时,该块内的所有操作都会被视为原子的,在该块内不会被其他线程打断。

然而,这种保证仅限于该同步块内。如果在同步块内调用了一个非同步的方法,那么该方法的操作就不受该同步块的保护,可能会被其他线程干扰。

你可能感兴趣的:(java)