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

测试 volatile 用法时,一直感觉有无voletile,结果是相同的,每个线程都可以看见变更已经改变了。原码如下

public class VolatileTest implements Runnable
{
    boolean flag = false;
    int i = 0;
    @Override
    public void run()
    {
        while (!flag)
        {
            i++;
            System.out.println(    i   );
        }
    }

    public static void main(String[] args)
        throws Exception
    {
        VolatileTest vt = new VolatileTest();
        new Thread(vt).start();
        Thread.sleep(100);
        vt.flag = true;
        System.out.println(    "stop");
    }
}

但是又觉得哪里有问题。后来偶然发现如果把while循环中的 System.out.println(    i   ); 拿掉,就有区别了。原来是System.out.println(    i   ) 影响了变更的可见性。pirntln原码:

public void println(String x)

{

        synchronized (this)

        {

                print(x);

                newLine();

        }

}

原来println有一个上锁的操作。使用了 synchronized 上锁会做以下操作:

  1. 获得同步锁;
  2. 清空工作内存;
  3. 从主内存拷贝对象副本到工作内存;
  4. 执行代码(计算或者输出等);
  5. 刷新主内存数据;
  6. 释放同步锁。

so so so。。。。。。。。

<think>好的,我现在需要帮助用户解决遇到的ParseException异常问题,具体错误信息是“Name unknown: System.out.println”。首先,我需要理解这个错误的背景和可能的原因。用户提到参考了某个站内引用,但看起来那个引用是关于构建目标的,可能和当前问题无关,所以暂时忽略。 接下来,考虑ParseException通常发生在解析表达式或代码时出现语法错误。用户遇到的错误信息指出“Name unknown”,这意味着解析器无法识别“System.out.println”这个名称。这可能是因为在调试表达式或某些特定环境中,直接使用System.out.println不被识别,或者上下文环境中缺少必要的导入或类路径设置。 可能的解决方向包括: 1. **检查调试表达式语法**:在调试器中,可能需要使用特定的语法或命令来执行打印操作,而不是直接调用System.out.println。例如,在JDWP调试器中,可能需要使用print命令。 2. **检查作用域和可见性**:确保在当前的调试上下文中,System类是可访问的,并且没有作用域限制。例如,在某些调试工具中,可能需要明确导入包或类。 3. **环境配置问题**:检查类路径是否正确配置,确保所有必要的库和类都被正确加载。如果类路径缺失,可能导致解析器找不到System类。 4. **使用调试器支持的打印命令**:有些调试器不支持直接执行Java语句,而是提供自己的命令来输出变量值。用户可能需要改用调试器提供的print或eval命令。 然后,我需要验证这些可能性。例如,在Java调试工具如jdb中,直接输入System.out.println可能会报错,因为调试器可能期望的是表达式而非语句。正确的做法可能是使用print命令加上变量名,或者使用eval来执行方法调用。 另外,检查用户是否在正确的上下文中执行命令。例如,是否在断点处暂停,变量是否在当前作用域中存在。如果System类没有被正确加载,可能需要检查类路径配置。 最后,总结解决方案,分步骤指导用户如何调整调试命令,检查环境配置,并建议替代方法。同时,生成相关问题帮助用户深入理解问题根源。</think>### 解析ParseException: 'Name unknown: System.out.println' 的解决方案 此异常通常出现在调试器(如Java调试工具)中直接使用`System.out.println`时,因调试表达式解析器无法识别该语句的上下文或语法导致。以下是逐步排查与解决方法: --- #### **1. 调试表达式语法限制** 调试器(如jdb、IDE内置调试器)对表达式的解析有限制: - **禁止直接调用`System.out.println`**:调试表达式通常仅支持变量、方法调用或简单运算,不支持完整的Java语句。 - **替代方案**:改用调试器支持的**打印命令**: ```bash print 变量名 # 直接输出变量值 eval 对象.toString() # 调用对象的方法 ``` --- #### **2. 检查类路径与作用域** 若必须使用`System`类,需确保调试环境正确加载了`java.lang`包: - **显式导入类路径**(部分工具需要): ```java import java.lang.System; ``` - **验证类路径配置**:检查调试启动参数是否包含`-classpath`或`-cp`,确保JVM能识别基础类库[^1]。 --- #### **3. 使用调试器专用命令** 在特定调试工具中需遵循其语法: - **jdb示例**: ```bash > stop in 类名.方法名 # 设置断点 > run # 运行程序 > print 变量名 # 输出变量值 > locals # 查看局部变量 ``` --- #### **4. 避免在条件断点中使用复杂语句** 若在条件断点中触发此错误: - **简化条件**:改用布尔表达式(如`x > 5`),避免调用方法或IO操作。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值