多线程原子性操作实例

package cn.itcast_06;

public class Ticket implements Runnable {
    private int tickets = 100;

    // @Override
    // public void run() {
    // // t1,t2,t3,t4
    // while (true) {
    // // t1,t2,t3,t4
    // // tickets = 100
    // // 假设t1抢到了CPU的执行权
    // if (tickets > 0) {
    // // 模拟正常的现象,我这里稍微的等待一下
    // // public static void sleep(long millis)
    // try {
    // Thread.sleep(10); // t1睡眠了,在睡眠的时候,t2抢到了CPU的执行权,t2进来后,也睡眠了。
    // } catch (InterruptedException e) {
    // e.printStackTrace();
    // }
    //
    // // t1醒过来,继续执行。
    // System.out.println(Thread.currentThread().getName() + "正在出售第"
    // + (tickets--) + "张票");
    // // 窗口1正在出售第100张票。
    // // tickets = 99
    // // 这仅仅是我们的理想状况,但是实际情况并不是这个样子的。
    // // 实际情况是这样的:每一次线程执行的程序应该是一个原子性的操作。也就是,这个操作,是不能再分割的操作。
    // // tickets--这个动作。
    // // tickets-1 = 99
    // // tickets = 99
    // // 如果你能想到这里至少是两个动作,那么,假设在减1的动作执行后,并没有给tickets重新赋值的时候,
    // // t2醒过来了,这个时候tickets还是100。所以,这个时候,窗口2正在出售第100张票。
    //
    // }
    // }
    // }

    @Override
    public void run() {
        while (true) {
            // tickets = 1;
            // t1,t2,t3,t4都过来了
            // 假设t1抢到了,
            // 假设t2抢到了,
            // 假设t3抢到了,
            // 假设t4抢到了,
            if (tickets > 0) {
                try {
                    // t1睡下了,
                    // t2睡下了,
                    // t3睡下了,
                    // t4睡下了,
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "正在出售第"
                        + (tickets--) + "张票");
                // t1醒过来了
                // 窗口1正在出售第1张票,tickets = 0;
                // t2醒过来了
                // 窗口2正在出售第0张票,tickets = -1;
                // t3醒过来了
                // 窗口3正在出售第-1张票,tickets = -2;
                // t4醒过来了
                // 窗口4正在出售第-2张票,tickets = -3;
            }
        }
    }

}




package cn.itcast_06;

/*
 * 通过实现Runnable接口改进卖票程序。
 *
 * 程序再次出现问题:
 * A:相同的票卖了多次。
 *         CPU的每一次执行,必须是一个原子性的操作。这个操作是不能在分割的。
 *             int i = 10;其实是两个原子性的操作。
 *             这样的话,tickets--其实也不是一个原子性的操作。
 *             可能在操作的中间部分,被其他的线程给执行了。这样就会有相同的票执行了多次。
 * B:出现了负数票的情况。
 *         因为线程的随机性。
 */
public class TicketDemo {
    public static void main(String[] args) {
        Ticket t = new Ticket();

        Thread t1 = new Thread(t, "窗口1");
        Thread t2 = new Thread(t, "窗口2");
        Thread t3 = new Thread(t, "窗口3");
        Thread t4 = new Thread(t, "窗口4");

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值