java基础之线程 认识volatile

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

线程部分:缓存

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

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

                              n. 挥发物;有翅的动物ide

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

可见性

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

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

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

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

这里直接讲原理会好点:在建立实例的时候,加了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原理和使用

相关文章
相关标签/搜索