JUC学习--volatile关键字&内存可见性

本文探讨了多线程环境下内存可见性问题及其解决方案。通过分析线程间共享变量的读写过程,揭示了内存可见性问题的原因,并对比了synchronized与volatile关键字的不同之处。

学习记录,若存在错误,请指出,谢谢!

首先,介绍一些内存可见性

内存可见性:当多个线程操作共享数据时,彼此不可见

为什么会导致这个情况?

在线程运行的过程中,JVM或者说是内存会为每一个线程分配一个独立的缓存用于提高效率。

举个例子:现在有一个读操作的线程和一个写操作的线程,对主存中的一个共享变量进行操作
写操作:线程先从主存中将共享变量读到线程独有的缓存中,然后对变量的值进行修改,最后再把修改后的变量的值写回到主存中。
读操作:读取主存中共享变量的值
但是,

读线程可能在写线程把修改的变量的值写回主存之前,就从主存中读了变量的值,但是这个值是原先的值

public class TestVolatile {

    public static void main(String[] args){

        ThreadDemo threadDemo = new ThreadDemo();
        new Thread(threadDemo).start();

        while(true){
          
                if(threadDemo.isFlag()){
                    System.out.println("--------");
                    break;
                }
            
        }
    }

}

class ThreadDemo implements Runnable{

    private volatile boolean flag = false;

    @Override
    public void run() {
        try {
            Thread.sleep(2000);
        }catch (InterruptedException e){
        }

        flag = true;
        System.out.println("flag = " + flag);
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

控制台打印的结果:


这就导致了一个问题,写线程已经把flag的值修改成了true,但是读线程(也就是代码中的main线程)并没有输出“-------”。

于是,我做了以下的修改

public class TestVolatile {

    public static void main(String[] args){

        ThreadDemo threadDemo = new ThreadDemo();
        new Thread(threadDemo).start();

        while(true){
            synchronized (threadDemo){
                if(threadDemo.isFlag()){
                    System.out.println("--------");
                    break;
                }
            }
        }
    }

}

在main线程中加上了synchronized关键字。于是


但是,使用了synchronize关键字之后,会导致程序的效率非常的低下。假设程序中有多个线程,每次访问synchronized()这行代码的时候,总是要判断是否有别的线程占有锁,如果有,当前的线程就只能阻塞,直到CPU下次空闲的时候才可能执行。

为了保证程序的效率,就不能够加锁,但是又要解决内存可见性的问题,就要提到volatile关键字了。
volatile关键字:当多个线程对共享数据进行操作时,可以保证该共享数据是内存可见的。
原因是:volatile使用了计算机底层的内存栅栏,可以将线程独立缓存中的值实时更新到主存中去,我们可以理解为,直接对主存进行操作。

当然,使用了volatile关键字也会对系统的性能有一点损耗,因为每进行一次操作,主存中的内容也会相应改变,但是效率比加锁还是要高得多的。

private volatile boolean flag = false;

将共享变量flag用volatile关键字修饰。


但是,volatile并不能直接替代synchronized关键字,因为相较于synchronized而言,volatile只是一种较为轻量级的同步策略

注意:
volatile不具备“互斥性”;

volatile不能保证“原子性”;

若要满足“互斥性”和“原子性”,则不能使用volatile



内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值