博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多线程模拟孩子抓糖经典问题
阅读量:3926 次
发布时间:2019-05-23

本文共 2456 字,大约阅读时间需要 8 分钟。

请听题

共11颗糖,有两个小孩,一个小孩一次只能抓三颗糖,另一个小孩一次只能抓四颗糖

如果剩余糖果不够当前小孩拿的数量,当前小孩不在抓糖,请用多线程模拟上面的描述

废话不多说先上码

public class TestFunction {
public static volatile AtomicInteger num = new AtomicInteger(11); //孩子线程 static class Child extends Thread {
private int getR = 0; private int r; CountDownLatch countDownLatch; public Child(int r, CountDownLatch countDownLatch) {
this.r = r; this.countDownLatch = countDownLatch; } @Override public String toString() {
return "孩子," + "一次拿" + r + "颗糖,共拿了" + getR + "颗糖"; } @Override public void run() {
try {
//等待 countDownLatch.await(); for (; ; ) {
//同步代码快保证原子性,保证判断和计算一致 synchronized (num) {
if (num.get() >= r) {
num.addAndGet(-r); getR += r; } else {
return; } } } } catch (InterruptedException e) {
e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(2); Thread thread1 = new Child(3, countDownLatch); thread1.start(); countDownLatch.countDown(); Thread thread2 = new Child(4, countDownLatch); thread2.start(); countDownLatch.countDown(); //等待两个线程执行完,回到当前线程 thread1.join(); thread2.join(); System.out.println("剩余糖:" + num); System.out.println(thread1); System.out.println(thread2); }}

问题解析

  1. 可见性

    问题可知糖一共有11颗,对于两个孩子都是可见,一个孩子拿完,另外一个孩子是能立马知道的,这就叫可见性。

    在代码中普通的参数对于不同线程,在某一个时刻看到值是不一样的。当线程A看到对象是1,其实只是在哪一个时刻看到的缓存区是1,主内存可能已经修改成2。为了避免这种情况。

    Java中的volatile 关键字就是为了解决这个问题,当前线程的缓存区的值发生变动时,会第一时间刷入主内存,同时会通知其他使用线程。

  2. 锁机制

    java中的锁机制JVM来保证数据同步的,而Lock则是在硬件层面,依赖特殊的CPU指令实现数据同步的。
    按照题意,在某一个时刻只能有一个线程在进行拿取糖的操作。所需要的对拿取糖的操作进行加锁,保证在任何时刻都只有一个孩子可以拿取糖。这里竞争不不激烈,所以直接使用
    synchronized对代码块进行加锁,同时保证数量判断和糖的拿取的原子性。

  3. 线程等待

    因为要模拟糖的拿取,所以我们要保证两个线程同时执行,同时开始拿取糖。所以这个时候CountDownLatch 出现了,在线程中await(),当CountDownLatch 的计数减到0时,所有线程会在继续从await()的下行代码开始执行。所以可以完美的模拟同时拿取的操作。

  4. 线程同步

    当执行所有线程,我为了看到结果使用Thread的join()方法,保证两个孩子线程执行完后,还回到当前主线程。
    join()表示将当前线程挂起,等待join的线程执行完,才会回到主线程。

转载地址:http://keugn.baihongyu.com/

你可能感兴趣的文章
ML.NET Cookbook:(16)什么是规范化?为什么我需要关心?
查看>>
WPF 修改(优化)Menu菜单的样式
查看>>
我开发了一款基于web容器的前端项目容器
查看>>
WPF实现环(圆)形菜单
查看>>
WPF 写一个提醒工具软件(完整项目)
查看>>
Windows 11 快速体验:开始菜单居中,全系圆角设计!
查看>>
异步流使用注意事项
查看>>
NET问答: 为什么仅有 getter 的属性,还可以在构造函数中赋值 ?
查看>>
WPF TextBox限制只能输入数字的两种方法
查看>>
【荐】牛逼的WPF动画库:XamlFlair
查看>>
如何绕过 TPM 2.0 安装 Windows 11 操作系统?
查看>>
为WPF播放GIF伤神不?
查看>>
.NET Core with 微服务 - Elastic APM
查看>>
生产力提升! 自己动手自定义Visual Studio 2019的 类创建模板,制作简易版Vsix安装包...
查看>>
考虑用Task.WhenAll
查看>>
关于面试,避开这几点,成功几率更大~~~
查看>>
堵俊平:开放治理是开源社区的终极之路 | DEV. Together 2021 中国开发者生态峰会...
查看>>
Linux实操--实用指令Day3
查看>>
Linux实操--实用指令Day4
查看>>
Linux实操--实用指令Day3
查看>>