java基础之线程 认识volatile

把java基础撸一边,从简单的开始。

线程部分:

对synchronize初步了解之后,知道大概原理暂时先放下,其他深入的后续再来(原因是我也还不会)。本章是对java提供的另一个关键字volatile认识一下,并使用它。

volatile 单词意思:adj. [化学] 挥发性的;不稳定的;爆炸性的;反复无常的

                              n. 挥发物;有翅的动物

我理解为是个可变的意思,不稳定。

可见性

在多线程开发中,对共享数据的操作是会有频繁操作的,为了保证在开发中,对会频繁变动的多线程操作数据保证一致性。java提供了synchronize,还有volatile。

在了解之前,知道一个词:可见--一个线程修改了这个变量,在另一个线程中能够读到这个修改后的值。这里注意一下,只是读到,而不是读写操作。不能保证原子性

synchronize是在保护他的代码块,不被同时两个线程进入操作出现,让线程是串行进入。重而保证了这个可见性。

volatile是怎么样保证参数的可见呢?

这里直接讲原理会好点:在创建实例的时候,加了volatile修饰词的话,在汇编中会多了一个lock指令。

lock指令:

在多处理器的系统上,1:将当前处理器缓存行的内容写回都系统内存

                                  2:这个写回内存的操作会使其他CPU里的缓存了该内存地址的数据失效


可以理解为volatile是读锁。在内存int a 的数据被线程1影响到了CPU线程2缓存的int i的数据,但注意。这里只相信读到的数据。但不影响线程2线程3这个共享内存的数据操作。这样也就可以知道,这个volatile的局限性。它不具备原子性,只有可见性。及时更新,但不限制其他数据退volition修饰的操作。

对于他的局限性。运行做如下操作


实例:

对一先修饰也volition的数据,程序只运行一方进行操作,其他线程不允许进行更改,只可以读。这也是叫轻量级锁的原因。下面展示代码

public class A3 {

    private volatile int a ;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }
}复制代码

public class Demo31 {

    public static void main(String[] age ){
        A3 a3 = new A3();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0 ; i <= 100 ; i++){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+ "修改值"+i);
                    a3.setA(i);
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0 ; i <= 100 ; i++){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+ "读取值"+a3.getA());

                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0 ; i <= 100 ; i++){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+ "读取值"+a3.getA());
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0 ; i <= 100 ; i++){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+ "读取值"+a3.getA());
                }
            }
        }).start();

    }

}复制代码

Thread-0修改值0
Thread-1读取值0
Thread-2读取值0
Thread-3读取值0
Thread-0修改值1
Thread-1读取值1
Thread-2读取值1
Thread-3读取值1
Thread-0修改值2
Thread-1读取值2
Thread-2读取值2
Thread-3读取值2
Thread-0修改值3
Thread-1读取值3
Thread-2读取值3
Thread-3读取值3
Thread-0修改值4
Thread-1读取值4
复制代码

可以看到,一旦线程被修改之后,读取到的数据就不会更改过来。但如果同时对数据进行修改

public class Demo31 extends Thread {

    public volatile int a = 0 ;

    public void set(){
        for (int i = 0 ; i  < 100 ; i++){
            a++;
            System.out.println(Thread.currentThread().getName() + "   a : "+a);
        }
    }

    @Override
    public void run() {
        set();
    }

    public static void main(String[] age ){
        new Demo31().start();
        new Demo31().start();
        new Demo31().start();
    }

}复制代码

结果

Thread-0   a : 1
Thread-1   a : 1
Thread-1   a : 2
Thread-0   a : 2
Thread-1   a : 3
Thread-2   a : 1
Thread-1   a : 4
复制代码

即使被volatile修饰之后,但并不会保证原子性。对于volatile的操作。要尽量保证是一个线程修改,其他线程只是读。

推荐文章:

深入理解volatile原理和使用


转载于:https://juejin.im/post/5c865bb75188257ed84792d6

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值