java 多线程下的原子操作了解认识

public class Test {
    
    boolean flag= false;

    public void changeFlag(){
        flag = true;
    }

    public void execute(){
        if(flag){
            System.out.println("execute....");
        }
    }
}

首先看上述代码:很简单,但是在这里如果有:线程A执行changeFlag方法之后,线程B再执行execute方法,试问,execute方法会不会打印出:execute....呢?  (是的,这个是多线程的案例,由他来引入;)

答案是:不一定会;

原因:

一般情况下,会执行打印的方法,就说说不会打印的理由,

线程A在执行完flag = true;之后,还未完全退出线程A,这时线程B抢到CUP资源,开始执行execute方法,判断flag的值时,flag的值依然为false;

因为在java内存模型中,多线程之间的变量值是不可见的;每个线程都有自己独立的working memory(工作内存),里面保存该线程使用到的变量的副本;程序在执行之前,所有变量都存在主内存当中,线程内存会往主内存中拷贝一份变量的副本,线程执行结束后,会将副本变量值赋给主内存中对应的变量,然后主内存再将修改后的变量赋值到每个线程的副本中;所以线程之间变量值的传递需要通过主内存完成;而线程之间的变量(全局)是不能互相访问的;

回到当前实例,所以这就是线程A中的flag为false的原因;

在这里涉及到java内存模型知识;针对上述例子大致说说原因,推荐链接:https://www.cnblogs.com/rocomp/p/4780532.html

通过上述例子余留了一个问题:如何才能使得线程之间的变量(全局)可见?

java语言支持可见性的实现方法:

synchronize、volatile、final

这里主要说说volatile:

如果在上述例子中flag声明前加上volatile;那么答案就是肯定的了;

但是volatile就可以万能了?当然不是:如下例子:

public class Test{

    public volatile int i=0;

    public void test1(){
        for(i;i<1000;i++){
            system.out.println(i);
        }
    }
}

上述代码,在多线程运行该方法的情况下,是否会打印到1000呢,如果不会可以加到10000或更大,然后让线程睡三秒,执行结果却不是我们想要的(1.到1000依次打印);

打印结果坑定少于1000,那么为什么会出现此问题呢?

这里就是原子操作的原因:For Example 例如:

以下多线程对int型变量x的操作,哪几个需要进行同步:( )
A. x=y; B. x++; C. ++x; D. x=1;

博文转载:https://blog.csdn.net/encoder1234/article/details/52228224

看了上面的链接博文后,是否明白原因了呢?  是的,上述答案除了D外,全是;

volatile虽然在线程之间变量有可见性,但是却并没有保证原子操作;

假如x是一个long或者double类型,且当前系统是32位的,那么,D选项也需要同步;

java对long和double的赋值操作是非原子操作!!long和double占用的字节数都是8,也就是64bits。在32位操作系统上对64位的数据的读写要分两步完成,每一步取32位数据。这样对double和long的赋值操作就会有问题:如果有两个线程同时写一个变量内存,一个进程写低32位,而另一个写高32位,这样将导致获取的64位数据是失效的数据。因此需要使用volatile关键字来防止此类现象。volatile本身不保证获取和设置操作的原子性,仅仅保持修改的可见性。但是java的内存模型保证声明为volatile的long和double变量的get和set操作是原子的。

那么怎样才能让全局变量既方便又安全呢?

请关注:CAS

推荐CAS博文:

https://www.jianshu.com/p/efb2024808a0

http://www.blogjava.net/xylz/archive/2010/07/04/325206.html

推荐volatile博文:

https://www.cnblogs.com/chengxiao/p/6528109.html

https://www.cnblogs.com/zhengbin/p/5654805.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java多线程是指在一个Java程序中同时运行多个线程,每个线程都可以执行不同的任务。Java多线程的实现可以通过继承Thread类或实现Runnable接口来完成。以下是Java多线程的一些基本概念和实现方法: 1. 线程的状态:Java线程有6种状态,分别是新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、等待(Waiting)和终止(Terminated)。 2. 线程的创建:Java线程的创建可以通过继承Thread类或实现Runnable接口来完成。继承Thread类需要重写run()方法,实现Runnable接口需要实现run()方法。 3. 线程的启动:线程创建后需要调用start()方法来启动线程,start()方法会自动调用run()方法。 4. 线程的同步:Java提供了synchronized关键字和Lock接口来实现线程的同步,避免多个线程同时访问共享资源导致的数据不一致问题。 5. 线程的通信:Java提供了wait()、notify()和notifyAll()方法来实现线程的通信,wait()方法使线程等待,notify()方法唤醒一个等待的线程,notifyAll()方法唤醒所有等待的线程。 以下是一个通过实现Runnable接口创建线程的例子: ```java public class MyRunnable implements Runnable { public void run() { System.out.println("MyRunnable running"); } } public class Main { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.start(); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值