0
点赞
收藏
分享

微信扫一扫

【多线程】结婚基金

何晓杰Dev 2022-04-27 阅读 155

一、故事引入

        80年代,小明和小红恋爱多年,准备结婚。于是两个人打拼多年,积攒了1万块钱的结婚基金,并且决定把它存放在银行。由于当时没有手机等通信设备,所以在两个人中,有其中一个人去取钱,另外一个人是不知道的。后来,小明迷上了追星,从银行里取出了1千块钱,于是卡里就剩下了9千块钱。这个时候,小红是不知道的,她依然觉得银行卡里有一万块钱。

二、实现思路

        小明类:多线程类,睡眠10毫秒,等线程醒来后,修改金额为9千,为了使得修改效果明显,当小明修改完后,打印出 “ 金额已经被修改了 ”

        小红类:多线程类,循环判断金额是否为1万,若不是,则打印 “ 金额不是1万了 ”

        存款类:普通类,定义一个共享数据money,(public static int money=10000)

三、代码实现

小明类:

public class XiaoMing extends Thread{

    @Override
    public void run() {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Money.money = 1000;
        // 为了让运行效果明显一点,输出小明修改
        System.out.println("金额已经被修改了");
    }
}

小红类:

public class XiaoHone extends Thread{

    @Override
    public void run() {
        while (Money.money==10000){
        }
        System.out.println("金额不是1万了");
    }
}

存款类:

public class Money {

    public static int money = 10000;

}

测试类:

public class DemoTest {
    public static void main(String[] args) {
        XiaoHone xh = new XiaoHone();
        XiaoMing xm = new XiaoMing();
        xh.start();
        xm.start();
    }
}

 运行结果:

        我们看到了,在小明类中,已经修改了共享数据的金额了。但是,程序还在运行,小红类也没有输出结果。

四、问题分析

        共享数据是存放在堆里的,当线程访问共享数据时,会复制一份共享数据存放在自己的线程栈中,当修改完成之后,会将自己线程栈中的数据进行修改,然后将线程栈中的数据赋值到堆数据里面去。但是如果线程没有对数据进行修改,那么他就会一直使用自己线程栈中的数据,即使堆数据修改了。

五、volatile关键字

        volatile强制线程使用线程栈数据之前,获取堆里的共享数据,修改存储类,其他类不变:

public class Money {

    public static volatile int money = 10000;

}

        运行结果:

        

         我们就达到了预期的结果了,程序也结束了,效果也出来了。

六、synchronized 同步代码块

        同样的问题,我们使用 synchronized 也可以解决这类问题,通过锁可以使得每个线程执行之前都要获取一次共享数据。实现代码如下图所示:

       小明类:

public class XiaoMing extends Thread{

    @Override
    public void run() {
        synchronized (Money.obj){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Money.money = 1000;
            System.out.println("金额已经被修改了");
        }
    }
}

        小红类:

public class XiaoHone extends Thread{

    @Override
    public void run() {
        while (true){
            synchronized (Money.obj){
                if (Money.money!=10000){
                    System.out.println("金额不是1万了");
                    break;
                }
            }
        }
    }
}

        存储类:

public class Money {
    public static int money = 10000;
    public static Object obj = new Object();
}

         测试类:

public class DemoTest {
    public static void main(String[] args) {
        XiaoHone xh = new XiaoHone();
        XiaoMing xm = new XiaoMing();
        xh.start();
        xm.start();
    }
}

        运行结果:

        好了,这就是结婚基金的问题!如果觉得有用的话,点个赞再走吧!

举报

相关推荐

0 条评论