Volatile关键字

  • Java语言允许线程访问共享变量,为了确保一致和可靠地更新共享变量,一个线程应该通过一个获取一个锁来确保它独占使用变量.一般来说,可以通过互斥来实现.
    Java语言提供了第二个机制----volatile关键字, 他比锁更简单.被声明为volatile的变量,可以保证所有的线程可以一致的访问这个变量.
  • volatile提供了稍弱的同步机制,用来确保将变量的更新操作通知到其他线程.当变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将改变量上的操作与其他内存操作一起重排序.volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此读取volatile类型的变量时总会返回最新写入的值.
  • 总之,一句话, volatile保证共享变量值改变后,能被其他所有的线程看到

一,不使用任何措施的示例

public class VolatitleTest {
    
    public static void main(String[] args) {
        OneThread one = new OneThread();
        TwoThread two = new TwoThread();
        
        one.start();
        two.start();
    }
    
    static int i = 0, j = 0;
     static void one() { i++; j++; }
     static void two() {
         System.out.println("i=" + i + " j=" + j);
     }
    
     static class OneThread extends Thread{
         public void run(){
             for(;;){
                 VolatitleTest.one();
             }       
         }
     }
     
    static class TwoThread extends Thread{
         public void run(){
             for(;;){
                 VolatitleTest.two();
             }
         }
     }
}

将会出现方法two()打印的j的值大于i的值. 出现的原因就是当线程1对i和j进行自增后, i更新的值不能被线程2看到.

二,使用synchronzied关键字

     static int i = 0, j = 0;
     static synchronized void one() { i++; j++; }
     static synchronized void two() {
         System.out.println("i=" + i + " j=" + j);
     }

使用synchronzied关键字后,方法one()和方法two()不能并发的执行,从而保证了共享变量i和j在方法one()结束后都被更新.

三,使用volatile关键字

    static volatitle int i = 0, j = 0;
     static void one() { i++; j++; }
     static void two() {
         System.out.println("i=" + i + " j=" + j);
     }
  • 当使用volatile修饰变量i,j的时候, 当i和j的值改变的时候, 线程立马的就可以看到改变后的值.
  • 但是当使用volatile之后,还会出现j比i大的情况,但是此时并不是因为i的值更改后不能被其他线程看见, 是因为多个线程同时操纵i和j造成的.
    与第二示例使用synchronized相比, synchronized的加锁机制可以确保可见性和原子性,而volatile仅仅可以确保可见性

参考:
<>

你可能感兴趣的:(Volatile关键字)