println导致的线程缓冲区刷新|一个volatile引起的思考

news/2024/5/20 6:11:35 标签: java, juc

问题引出:

今天在看volatile的时候,自己写了个例子,
发现即使没有volatile,我程序也照常跑了

描述

首先看看这个情况的描述

第一个代码是有关何时以及如何使用volatile的示例,熟悉volatile的一定知道,为了使程序成功运行,我们需要添加volatile。

第二个代码表示,即使没有volatile,该程序情景仍然可以成功运行。

第一段代码, 经典的volatile使用案例

java">
public static int num=1;

public static class MyThread extends Thread {
    // flag
    private boolean flag = false ;
    public boolean isFlag() { return flag;}
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) { e.printStackTrace();
        }
// change flag to true
        this.flag = true ;
        System.out.println("flag=" + flag);
        this.flag=true;
    }
}
// main函数
static void testWithOutVolatile(){
    MyThread t=new MyThread();
    t.start();
    while(true) {
        boolean is=t.flag;
        if (is) {
            System.out.println("run======");
        }
    }
}

启动后,除非使用volatile,否则主线程将找不到flag变量的更改
在这里插入图片描述

但是如果下面这段代码,程序他,竟然看到了flag的变动

java">static int amb=0;
static void testSimple(){
    Thread t1=new Thread(()->{
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        amb++;
    });
    Thread t2=new Thread(()->{while(true) {
        if (amb == 0) {
            System.out.println("no");
        }
        if (amb != 0) {
            System.out.println("SUc");
            break;
        }
    }});
    t2.start();
    t1.start();
}

问题的解决

自己动手修改了一下代码尝试了一下,
发现如果删除print,线程就看不到变化,
只要随随便便加一个print语句,线程就看到了变化

java">Thread t2=new Thread(()->{while(true) {
        System.out.println("no");
        if (amb != 0) {
            System.out.println("SUc");
            break;
        }
    }});

在这里插入图片描述

问题似乎变的清晰了,点开print的代码,

java"> public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

这里有一个synchronized ,synchronized大家都知道吧,重量级锁,线程将释放资源等待
线程执行到这里时,释放了自己的资源,发生了“线程切换”,线程的缓冲区就随之消失,
等到第二次执行到这里的时候,重新获取了变量的值
所以看起来似乎不用使用“volatile”

更多文章,看https://blog.csdn.net/weixin_44494373


http://www.niftyadmin.cn/n/1689872.html

相关文章

浅析JWT| JWT是啥子,Java构建JWT

小声bbb 说到系统的安全识别,记得自己第一个项目,用的就是session,用户登录进来以后,给他session标记登录,记录id进去,轻轻松松,设计的操作也很简单,类似操作HashMap。 这大概也有1年…

MFC EditCtrl 弹出“请输入一个整数。”的问题

弹出的原因是,EditCtrl绑定了一个int类型的变量,当为空的时候,执行UpdateData(true),则会弹出,尤其如果在KillFocus函数中调用UpdateData时,会无限弹出警告对话框。

MySQL事务浅析|由浅入深

关注可乐可乐可,查看更多有趣文章 https://blog.csdn.net/weixin_44494373 MySQL事务浅析|由浅入深 很多人都在讲事务,事务是个啥,我感觉我没开事物也没什么事情啊,学事务有必要吗? 今天照旧,本文在一开始…

MFC如何在对话框上画分割线

拖一个PictureCtrl控件,拉成直线,然后color选项选etched就好了。

轻松理解AQS框架 |不会有人看了不懂吧

本文作者:可乐可乐可,博主个人主页:可乐可乐可的个人主页 轻松理解AQS框架 本文需要以下知识铺垫:Java、临界区、信号量、锁 AQS(AbstractQueuedSynchronizer,抽象队列同步器)是Java中重入锁Ree…

MFC中ComboBox的排序问题

使用ComboBox的时候,如果有个两个变量和其关联(其中一个和控件关联,另一个为保存的内容,第二个变量不会自动变化)。这时候为了对应 第二个变量和comboBox的关系时,需要保证comboBox的下拉顺序是确定的&…

Go Web开发入门指南<前半>

Go Web开发入门指南 关注博主不迷路:可乐可乐可 内容:Go Web开发套装,Gin,Gorm,viper,validator,zap,go-redis,grpc 本文难度:适合入门 一般开发web项目&…

Windows Server 2008 使用测试

第一次使用服务器操作系统,自己在windows10 上写的程序,测试是否可以运行到服务器上。 1、使用vs2015编译的程序(共享MFC运行时库),则会报错,说缺少dll。解决方法是安装 “vc2015运行库下载”。 https:/…