`
heiliguai
  • 浏览: 14514 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类

debug模式下所有变量有volatile的效果?

    博客分类:
  • java
阅读更多

java中非volatile变量读取是从工作内存中读取,不一定可以读到主内存的最新数据。volatile变量保证每次读取都要从主内存中拿。

 

写了一段代码来验证这一点

 

public class MemoryMode {

    private volatile boolean flag = false;//这个类型是volatile的时候,结果是conditionChanged:true

    public void setFlag(){
        flag = true;
    }

    private  boolean conditionChanged = false;

    public static class LoopRunnable implements Runnable{
        private MemoryMode memoryMode;
        public LoopRunnable(MemoryMode memoryMode){
            this.memoryMode = memoryMode;
        }
        public void run() {
            while (true){//标记未改变,一直循环
                if(memoryMode.flag){
                    memoryMode.conditionChanged = true;
                    break;
                }
            }

        }
    }

    public static class SetFlagRunnable implements Runnable{
        private MemoryMode memoryMode;
        public SetFlagRunnable(MemoryMode memoryMode){
            this.memoryMode = memoryMode;
        }
        public void run() {
            memoryMode.setFlag();//改变标记值
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MemoryMode memoryMode = new MemoryMode();

        LoopRunnable loopRunnable = new LoopRunnable(memoryMode);
        Thread a = new Thread(loopRunnable);
        Thread b = new Thread(new SetFlagRunnable(memoryMode));

        a.start();
        Thread.sleep(10000);
        b.start();

        a.join();
        b.join();

        System.out.print("conditionChanged:"+memoryMode.conditionChanged);
    }
}

 

 

上面这段代码申明了一个volatile修饰的名称为flag的变量,初始值为false。启动一个线程a,run方法是一个死循环,flag为true时才退出循环。然后启动另外一个线程b,改变flag的值到true。因为flag一个volatile变量,值被线程b改变后,对线程a是立即可见的,所以可以代码可以正常退出。

 

把上面的代码修改一下,去掉flag对象的volatile修饰。期待a线程一直读不到flag的值变为true,代码一直循环,不能正常退出。

 

在Intellij里,选择run as application,和期望的一样,代码确实不能正常退出。但是,如果选择的是debug as application的话,代码可以正常退出的,和标记为volatile的效果一样。

 

可以猜想,debug模式下,所有变量都是从主内存中读取的。

分享到:
评论

相关推荐

    Debug调试与Release调试区别

    在Debug版本中,为了提高调试的便利性,编译器可能会保留所有标记为`volatile`的变量,即使这些变量在实际运行中并没有发生变化。这样做有助于确保程序状态的一致性和可预测性,尤其是在多线程环境中。 而在Release...

    详解C中volatile关键字

    volatile关键字的作用是提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,...

    volatile的作用

    然而,在debug模式下执行时,由于编译器进行了优化,导致`b`的值仍然为10,而不是更新后的32。这说明了如果没有使用`volatile`关键字,编译器可能会缓存`i`的值,即使其实际值已经发生了变化。 #### (2) 使用`...

    Visual_Studio中的debug和release版本的区别

    * volatile 型变量:volatile 告诉编译器该变量可能被程序之外的未知方式修改(如系统、其他进程和线程)。优化程序为了使程序性能提高,常把一些变量放在寄存器中(类似于 register 关键字),而其他进程只能对该...

    变量的存储类型.zip

    在“Debug”目录下,可能包含编译和调试这些代码时生成的中间文件和输出,这对于调试和理解程序的运行情况非常有用。 总之,变量的存储类型是编程中的核心概念,理解和熟练运用这些类型能帮助开发者编写出更加健壮...

    多线程编程【技术文章汇编】经典

    2. **volatile关键字**:在Java和C++中,volatile关键字用于确保多线程环境下的可见性和有序性,但不能保证原子性。 3. **原子操作**:不可分割的操作,例如 increment 操作,需要通过原子操作保证在多线程环境中的...

    windows线程同步

    在多线程环境下,如果一个变量可能被其他线程修改,将其声明为`volatile` 可以保证其可见性,但不保证原子性。 2. **Interlocked函数系列**: Windows API 提供了一系列的`Interlocked`函数(如`...

    C语言关键字

    在开发过程中,`volatile`的使用有助于保证程序在不同编译器和优化级别下的正确性。在Debug版本中,编译器的优化程度较低,程序可能运行正常,但在Release版本中,由于编译器的更激进优化,未声明为`volatile`的变量...

    c# volatile 关键字的拾遗补漏

    需要注意的是,volatile 关键字并不能解决所有线程安全问题,它仅仅保证了变量的可见性,而不能保证操作的原子性。例如,如果你有一个计数器需要在多线程中递增,volatile 无法防止竞态条件,你需要使用锁或其他并发...

    内嵌汇编用法及分析 asm

    - **输出**:格式为 `"=c"(变量名)"..."`,其中 `"=c"` 表示输出约束,用于告诉编译器输出变量的值可能会被修改。 - **输入**:格式为 `"c"(变量名)"..."`,其中 `"c"` 表示输入约束,用于告诉编译器输入变量的值...

    java多线程学习笔记02(csdn)————程序.pdf

    但synchronized可以确保在释放锁之前,所有修改过的变量都可见,而volatile则没有这个保证。 Java 1.5引入的Lock接口扩展了同步机制,提供了更灵活的控制。ReentrantLock是Lock的一个实现,它也是可重入的,意味着...

    C语言程序设计第四版何钦铭课后习题及答案.pdf

    例如,auto 声明自动变量,break 跳出当前循环,case 开关语句分支,char 声明字符型变量或函数返回值类型,const 声明只读变量,continue 结束当前循环,开始下一轮循环,default 开关语句中的“默认”分支,do ...

    ARM资料(By打嗝-END122).txt

    - **volatile**: 表明变量可能在没有明确程序控制的情况下发生变化,通常用于硬件接口编程中。 ### LED闪烁示例 最后,文件中还包含了一个简单的LED闪烁程序示例,展示了如何使用ARM汇编和C语言混合编程来控制LED...

    ARM资料(By打嗝).txt 东华理工大学

    - 文件中提到了ARM7的不同工作模式,包括用户模式、快速中断模式(FIQ)、普通中断模式(IQR)、系统调用模式(SVC)、中止模式(Abort)、未定义模式(Undefined)和系统模式(System),每种模式对应不同的特权级别。...

    全面解析《嵌入式程序员应该知道的16个问题》

    `volatile`关键字用于指示编译器不要优化对某个变量的访问。 **示例**: ```c volatile int i = 0; // 定义了一个易变的整型变量 ``` **解析**: - 对于硬件接口或外部设备的状态等,使用`volatile`可以确保程序...

    04-并发编程面试题-重点.docx

    volatile 关键字是指在多线程环境下,如何保证变量的可见性和原子性。 volatile 关键字的作用:保证变量的可见性、保证变量的原子性。 九、Lock 机制 Lock 机制是指在多线程环境下,如何保护共享资源不被多个线程...

    单片机程序死机和程序跑飞原因分析

    为了解决这个问题,通常需要在全局变量前使用关键字volatile进行修饰,这可以告诉编译器该变量可能会被硬件或中断服务程序改变,避免编译器对这些变量进行优化处理。此外,在读取这些变量之前,应当暂时关闭全局中断...

    java 开发规范,方便程序员开发代码时的规范

    - 日志级别分为DEBUG、INFO、WARN、ERROR,根据需要选择合适的级别。 10. **测试**: - 编写单元测试用例,确保代码功能的正确性。 - 使用JUnit、Mockito等工具进行测试驱动开发。 以上仅为部分Java开发规范,...

    面试题-c++面试题一

    一个变量可以多次声明,但只能有一次定义。例如: ```cpp extern int A; // 声明A为已定义的外部变量 int main() { extern int A; // 声明 dosth(); // 使用 } int A; // 定义 ``` 使用`extern`关键字声明...

Global site tag (gtag.js) - Google Analytics