证明static 关键字并不能保证线程可见性

2 篇文章 0 订阅

1.static : 标识这个属性是实例共享的。(也可以称作类变量)

2.volatile:标记该属性是易变的,被修饰的属性被修改后,别的线程每当用到该属性都要重新去读取。

线程运行时会将用到的数据拷贝一份,放到自己的线程栈中,volatile会让该线程修改数据后写回原数据,并通知别的线程重新读取。

疑惑:static 修饰变量是类变量,被修改后别的线程也“应该”能读取到,是不是也具有线程可见性?

证明:代码如下

package highconcurrency;

/**
 * <b>测试volatile关键字</b></br>
 *
 * @Company 子虚</ br>
 * @Version V1.0
 * @Author 花月
 * @Date 2020/8/13 8:46
 */
public class TestVolatile {
    public static void main(String[] args) {
        MyData myData = new MyData();
        new Thread(() -> {
            System.out.println("线程启动a值为:"+myData.a);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            myData.changeA();
            System.out.println("线程结束a值为:"+myData.a);
        }).start();
        //如果读取不到最新a值这里会死循环
        while (myData.a==0){
            //循环里不能写代码,不然不增加volatile也能读取最新的a值,猜想这里的操作导致while循环重新读取了a的值
            /* try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
//            System.out.println(myData.a);
        }
        System.out.println("a的值改变,并且被主线程看到");
    }
}

class MyData{
    //设置 volatile,static,和不加关键字。只有volatile能达到线程可见性。
//    static int a = 0;
    volatile int a = 0;
//    int a = 0;

    void changeA(){
        a = 10;
    }
}

当a属性不加static和volatile修饰时执行结果:

增加volatile关键字执行结果:

增加static修饰执行结果:

结论:

只有volatile具有线程可见性。

测试的时候while循环里不能写代码,写代码会导致不加volatile修饰出现和加volatile一样的效果.可能循环里的操作,导致重新读取a得值了。哪位大佬清楚这里原因请告知,不胜感激。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值