本文记录“System.out.println”输出保证可见性

SpringBoot项目日志配置实战:从System.out.println到slf4j+logback的优雅升级 本文详细阐述了SpringBoot项目如何从低效的System.out.println日志方式,升级为基于slf4j门面和logback实现的专业日志体系。通过性能对比、核心原理剖析和五步实战配置,指导开发者构建支持异步输出、级别动态调整、文件滚动归档的生产级日志系统,显著提升应用的可观测性与运维效率。 阅读详情

正常使用volatile保证线程之间数据的可见性,但是今天才发现 输出 也可以保证数据的可见性,测试一下果然如此

原因是输出代码底层使用了synchronized 锁,这个锁保证了线程在进入代码块之前数据的同步(从主内存重新取数据),同时保证了代码块结束后数据的一致(将修改后的数据刷回主内存)。

测试代码:

package com.tuling;

public class Volatile_test1 {
    private volatile boolean flag = true;

    public void load(){
        System.out.println(Thread.currentThread().getName() + "开始执行......");
        System.out.println("while前的flag:" + flag);
        while (flag){
            //一直加载

            //测试 输出 能不能保证可见性
            System.out.println(flag);
        }
        System.out.println("while后的flag:" + flag);
    }

    public void refresh(){
        /*结束加载*/
        flag = false;
        System.out.println(Thread.currentThread().getName() + "修改flag:" + flag);
    }
    public static void main(String[] args) throws InterruptedException {
        Volatile_test1 test = new Volatile_test1();
        
        Thread threadA = new Thread(()-> test.load(),"threadA");
        threadA.start();
        
//        Thread.sleep(1000);
        
        Thread threadB = new Thread(()->  test.refresh(), "threadB");
        threadB.start();

    }
}

 

下面是今年最强AI——Deepseek(国产)给出的详解

目录

### 1. **`System.out.println` 的实现**

### 2. **内存屏障(Memory Barrier)**

### 3. **JVM 的优化行为**

### 4. **实际效果**

### 5. **为什么不依赖 `System.out.println` 保证可见性?**

### 总结


`System.out.println` 本身并不直接保证可见性,但在实际使用中,它常常表现出类似的效果。这是因为 `System.out.println` 内部的实现机制和 JVM 的优化行为间接地影响了线程的可见性。以下是详细原因:

---

### 1. **`System.out.println` 的实现**


`System.out.println` 是一个同步方法(`synchronized`),它的内部实现如下:
```java

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


```
- **同步机制**:`synchronized` 关键字会强制线程在进入和退出同步块时执行以下操作:
  - 进入同步块时,线程会从主内存中重新加载所有变量的最新值(刷新工作内存)。
  - 退出同步块时,线程会将工作内存中的修改写回主内存。
- 因此,`System.out.println` 的同步机制会间接地刷新线程的工作内存,使得其他线程对共享变量的修改变得可见。

---


 

### 2. **内存屏障(Memory Barrier)**


- `synchronized` 块会隐式地插入内存屏障,防止指令重排序,并确保变量的修改对其他线程可见。
- 当调用 `System.out.println` 时,JVM 会插入内存屏障,强制将线程的工作内存与主内存同步。

---


 

### 3. **JVM 的优化行为**


- JVM 会对代码进行各种优化,例如指令重排序。然而,`System.out.println` 是一个相对“重量级”的操作,涉及 I/O 操作和同步机制。
- 由于 I/O 操作本身比较耗时,JVM 可能会减少对 `System.out.println` 附近代码的优化,从而间接地减少了指令重排序的可能性,使得变量的修改更容易被其他线程观察到。

---


 

### 4. **实际效果**


- 在多线程调试中,`System.out.println` 经常被用来观察变量的值。由于上述原因,它通常会显示出变量的最新值,给人一种“保证了可见性”的错觉。
- 然而,这并不意味着 `System.out.println` 是一个可靠的同步工具。它的可见性效果是间接的,依赖于同步机制和 JVM 的行为,而不是设计上的保证。

---


 

### 5. **为什么不依赖 `System.out.println` 保证可见性?**


- **非确定性**:`System.out.println` 的可见性效果是偶然的,依赖于 JVM 的实现和优化行为,不能保证在所有情况下都有效。
- **性能问题**:`System.out.println` 是同步的,且涉及 I/O 操作,性能开销较大,不适合用于实际的同步需求。
- **设计原则**:Java 提供了明确的同步工具(如 `volatile`、`synchronized`、`java.util.concurrent` 包),应该使用这些工具来保证可见性和线程安全。

---


 

### 总结


`System.out.println` 之所以看起来“保证了可见性”,是因为它的同步机制和 I/O 操作间接地触发了内存同步。然而,这种行为是偶然的,不能依赖它来实现线程安全。在实际开发中,应该使用 Java 提供的同步工具来明确地保证可见性和线程安全。

相关推荐

COMSOL 6.4安装全攻略:安装包获取、许可证配置与避坑指南

多物理场仿真是现代工程与科研中不可或缺的技术手段,其核心原理在于将电磁、结构、流体、传热等不同物理过程的耦合效应置于统一环境中求解,从而真实模拟复杂系统行为。这类仿真平台能大幅提升产品研发与设计验证效率,广泛应用于电子散热、声学分析、电力设备等领域。在部署最新版本仿真软件时,安装与许可证配置往往成为影响工作效率的关键环节。本文系统梳理COMSOL 6.4在Windows平台的安装全流程,涵盖安装包获取、系统依赖准备、许可证配置、常见报错排查等实用经验,帮助工程师与科研人员一次性完成环境搭建,把更多时间投入真

weixin_30000735的博客 1328

Java | System的一些用法

Java | System的一些用法 一、标准输入输出 System.out.println():向标准输出流打印并换行。 System.out.print():向标准输出流打印但不换行。 System.err.println():向标准错误流打印并换行,通常用于输出错误信息。

yingzix688的博客 793

comfyui从入门到精通二:提示词规则详解

《AI绘画提示词使用全指南》摘要: 本文系统解析AI绘画提示词的核心规则与实用技巧。关键点包括:1) 空格与下划线的本质差异,webui会自动转换但comfyui保留原格式;2) 数字与单词表达(如1girl/one girl)会导致风格变化;3) 三种权重控制方式(数值标注、括号嵌套、位置效应),其中数值标注最直观有效;4) 位置衰减公式揭示提示词排序对效果的影响权重。同时指出当前AI绘画仍存在角色一致性等更复杂的技术瓶颈。全文通过多组对比实验,为创作者提供从基础语法到高阶控制的完整解决方案。

ScottePerk的博客 1922

System.out.println影响内存可见性

看到这个说明你正在学习java内存模型 先说为什么System.out.println会影响内存可见性 public class ThreadVisibilityTest1 { public static boolean flag = true; public static void main(String[] args) throws Exception{ new Thread( () -> {

JSH的博客 671

【东华大学oj】找到最大数(一维数组->中等)

一天,老师布置了一个作业,要求对一串数字各不相同的数字串进行排序,大的在前,小的在后。接着,我从数字串中的第二个数字开始往后找,找到最大的一个,然后与第二个数字交换,这样的话我就能够确定排序后数字串中的第二个数字;明明研究发现,他的这个想法中最重要的一环就是在一串数字中找到最大的那个,然后与第一个数字交换,可是明明毕竟刚刚开始学习程序设计不久,无法写出较复杂的程序,所以明明想让你这位程序设计专家帮他的忙,帮助他把这段核心程序写出来,然后明明只需模仿着写就可以了。时间限制: 1S类别: 一维数组->中等。

的博客 524

T100服务端接口实战:从注册到日志排查的全链路开发指南

本文提供了一份T100服务端接口开发的全链路实战指南。从程序注册与框架签出开始,详细讲解了接口的数据结构设计、核心业务逻辑编写,到最终的部署上线与调用验证。文章重点分享了如何利用日志文件高效定位和排查接口问题,帮助开发者快速掌握T100接口开发的关键步骤与实用技巧。

weixin_28831399的博客 297

Java中System.out.println()为何会影响内存可见性

本文主要说明System.out.println为啥会影响内存的可见性? 先看示例代码: public class T implements Runnable { private boolean flag = false; public boo...

m0_37695902的博客 646

VC中基于TWAIN协议控制扫描仪-----初级版

PS:本人是C++小白一枚,在研究此功能时不知走了多少弯路

a1101000099的专栏 8788

详解Java多线程之内存可见性

可见性:一个线程对共享变量值的修改,能够及时的被其他线程看到。共享变量:如果一个电量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量。 JAVA内存模型(Java Memory Model)描述了Java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节。所有变量都存储在主内存中。每个线程都有自己独立的工作内存,里...

weixin_30710457的博客 204

HMC5883L磁力计驱动开发:I²C通信、校准与FreeRTOS集成

磁力计是惯性导航与电子罗盘系统的核心传感器,其输出原始磁场数据需经精确采集、单位换算与误差补偿才能用于姿态解算。基于各向异性磁阻(AMR)原理的三轴磁力计,如HMC5883L,依赖稳定I²C通信获取12位有符号磁场采样值,并通过增益配置、硬软铁校准及温度补偿提升物理量精度。在嵌入式实时系统中,驱动层须保障数据的时间一致性与抗干扰鲁棒性,避免总线挂死、字节错位或量程误配等典型问题。本文围绕HMC5883L这一广泛使用的停产但仍在产线服役的磁传感器,详解寄存器配置、定点单位转换、八方位校准算法及FreeRTOS

weixin_42594427的博客 145

【Agent】AI Agent架构趋势及演进

本文系统介绍了AI Agent架构的发展趋势和技术框架,涵盖单Agent与多Agent系统设计、提示词工程与上下文管理、SpringAI开发框架等关键技术。重点阐述了AI原生应用参考架构,包括Nacos配置管理、Higress AI网关、RocketMQ会话状态管理等核心组件解决方案。同时深入探讨了AI应用可观测性体系,包含OpenTelemetry全链路追踪、关键指标监控以及基于LoongSuite开源工具的数据采集评估方法,为构建高效可靠的AI应用提供了全景式技术参考。

一个内容严谨、方向前沿、极具实践价值的AI大模型技术分享站 1104

System的标准输入输出流

1.输入和输出流 程序对应的基本输入为键盘输入,基本输出为显示器输出。Java中,System类的in和out两个成员代表了基本输入输出的抽象 System.in: System.in是InputStream, 标准输入流, 默认可以从键盘输入读取字节数据 注意:System.in流是无需关闭的 案例: package system; import java.io.BufferedInputStream; import java.io.IOException

tianhumanong的博客 1176

【华为OD机试真题 新系统】1043、魔法咒语组合 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS)

【华为OD机试真题 新系统】1043、魔法咒语组合 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS) 华为od机试,华为od机试真题,华为od机试E卷,华为odE卷,华为od机试真题E卷,华为OD,华为OD机试,华为OD机试真题,华为od机考,华为od机试D卷,华为od机试真题D卷,华为od手撕代码,华为od,华为od机试C卷,华为od e卷,华为2026e卷,od机试,2026E卷,华为OD机试E卷,什么是华为od,华为od介绍,全面了解华为od,2026华为od,如何备战华为od

KJ.JK 281

秋招Java-面试官就System.out.println()考了我半个小时?

学了这么久的面向对象编程,那如何用一行代码体现呢? 老师告诉我,如果你能自己读懂System.out.println(),就真正了解了Java面向对象编程的概念 System.out.println("hello world"); hello world Process finished with exit code 0 首先分析System源码 System就是Java自定义的一个类 ...

末尾卡片和博主交流学习! 1万+

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

System.out.println的可见性问题?

贴出代码: public class VisibilityDemo { public static void main(String[] args) throws InterruptedException { VisibilityTest v = new VisibilityTest(); v.start(); Thread.sleep(1000); v.stoplt(); Thread.slee...

u014632958的博客 914

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

System.out.println()对共享变量和多线程的影响,为什么会造成while循环终止

最近在了解volatile关键字,众所周知volatile可以保证共享变量的可见性,本文是记录在学习volatile过程中遇到的有趣事件。 首先看下面的代码: private static boolean isStop = false; public static void main(String[] args) { new Thread() { ...

Coder-文小白的博客 1161

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

为什么System.out.println()可以保证变量的可见性

private void newLine() { try { synchronized (this) { ensureOpen(); textOut.newLine(); textOut.flushBuffer(); charOut.flushBuffer(); if (autoFlush) ...

payne608的博客 760

Java服务器开发的日志框架介绍和System.out.println()不适合日志

在实际的服务器开发中,更推荐使用专门的日志库,如 Log4j, SLF4J, java.util.logging 等,它们提供了丰富的日志配置选项,可以满足不同场景下的日志记录需求。尽管如此,在后台应用开发过程中,System.out.println 仍然有其临时调试用途,只是不适合长期作为正式的日志解决方案。

宋冠巡的博客 1128

再使用System.out.println()打印收拾东西回家

今天没事干的时候,无意间点到了一个中的println()方法,一个闪亮的关键字冲击着我的眼睛。不知道大家知不知道,那就是加锁的。但凡有锁的地方肯定会性能是有损耗的,当然得在并发的情况下!无锁—>偏向锁—>自旋锁—>轻量级锁—>重量级锁轻量级锁和偏向锁通常不涉及内核态切换在到重量级锁时涉及到用户态和内核态的切换,很影响性能的!有兴趣的可以自己研究一下synchronized的锁升级和降级!下面我们回归正题,看一下这个!虽然在快速测试和学习阶段很有用,但在实际的应用程序中,频繁使用它可能会导致一系列问题。

小王博客基地 358

5年半老程序员被System.out.println() 考懵逼了...

开发者(KaiFaX)面向全栈工程师的开发者专注于前端、Java/Python/Go/PHP的技术社区去年秋招面试我被问及,你如何理解System.out.println() ?学了这么久的面向对象编程,那如何用一行代码体现呢?如果你能自己读懂System.out.println(),就真正了解了Java面向对象编程的含义面向对象编程即创建了对象,所有的事情让对象帮亲力亲为(即对象调用方法)Sys...

AI研习社 187

关于可见性

t线程中有一个while-true循环,我们试图通过在主方法中将run置为0,让t线程停下来,但是执行程序我们发现,并没有和我们预想的一样,t线程会停下来 尝试分析这个过程 初始状态,t线程刚开始从主内存读取了run的值到工作内存 因为t线程要频繁的从主内存中读取run的值,JIT编译器会将run的值缓存至自己内存中的高速缓存中(底层是CPU中的缓存),减少对主存中run的访问,提高效率 一秒之后,main线程修改了run的值,并同步至主内存,而t是从自己工作内存中的高速...

weixin_58104242的博客 324

为什么我的代码没有陷入死循环

首先说一下volatile这个关键字的t特性: 1.保证可见性,volatile保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。 2.保证有序性,禁止进行指令重排序, 3.不保证原子性,volatile也无法保证对变量的任何操作都是原子性的 执行一下代码,测试一下volatile关键字 import java.util.concurrent.TimeUnit; public class VolatileTest { private sta

qq_47067442的博客 439

Java EE:2.多线程-初阶(第四弹):synchronized 锁+内存可见性

Java EE:2.多线程-初阶(第四弹)

要努力去发光,而不是被照亮~ 612

Java基础核心:逻辑控制与输入输出实战要点解析

程序设计的本质,可以抽象为输入、处理和输出三个环节。在Java开发中,逻辑控制(if/else、switch、for、while)与输入输出(System.in/out、Scanner、文件读写)正是支撑这一闭环的两大基石。理解条件判断与循环机制,能够让程序具备决策和重复执行的能力;掌握控制台与文件的IO操作,则能实现数据与外界的高效流通。无论是初学者系统梳理JavaSE知识,还是开发者准备面试复盘,这两块内容都值得重新审视。从分支与循环的选用,到Scanner的常见坑、文件读写的编码问题,再到结合猜数字游

weixin_33766805的博客 174

Java入门基础教程:从变量到输出语句,新手快速掌握Java编程核心知识点

但这里有个小细节得注意,Java 里的变量是有 “类型” 的,你存数字就得用 “int” 类型,存文字就得用 “String” 类型,可不能随便乱存,不然程序就会报错,就像你不能把大象塞进衣柜里一样,对吧?这些小细节看着不起眼,可一旦忽略了,结果就会跑偏,跟做饭放错调料似的,本来想做甜口,结果做成了咸口,多闹心啊!初学者不用一开始就搞那些复杂的工具,先装个 JDK(Java 开发工具包),再用记事本写代码就行,写完之后通过命令行编译运行,虽然麻烦点,但能帮你搞懂 Java 程序是怎么一步步跑起来的。

2501_93091108的博客 351

Java学习记录——错题总结(三)

第一套 1.编译java程序的命令文件是( ) B A. java.exe B. javac.exe C. applet.exe javac.exe是编译功能javaCompiler java.exe是执行程序,用于执行编译好的.class文件 javadoc.exe用来制作java文档 jdb.exe是java的调试器 javaprof.exe是剖析工具 2.在java中,无论在何处调用,使用静态属性必须以类名做前缀。 错误 如果是本类使用,可以直接就用静态变量名。 如果是其他类使用,可以使用类名来调用,

weixin_44099043的博客 775
上一篇: bean的生命周期+作用域
new2MySQL
博客等级 码龄5年 255粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值