JAVA_volatile

https://www.cnblogs.com/dolphin0520/p/3920373.html

当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
而普通的共享变量不能保证可见性,因为普通共享变量被修改之后,什么时候被写入主存是不确定的,当其他线程去读取时,此时内存中可能还是原来的旧值,因此无法保证可见性。

volatile作用
一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

2)禁止进行指令重排序。

重点
无法保证原子性,可以保证有序性,(可见性 报有疑问,希望高手指点)
个人理解:
一开始从无法保证原子性这一点出发,让我怀疑volatile到底能不能保证可见性,因为A线程的读写操作只进行到读,cpu就转而执行B线程的写操作,而当重新执行A线程的第二部写操作时,B线程之前所做的写操作就会被覆盖,出现了脏数据。
如果说保证可见性,那么B线程执行写操作后A线程就应该重新获取一次变量值,这才是真正的可见性。

package org.kevin.lucene;

public class VolatileTest {

    private static volatile String string = "";
    
//  public int get() {
//      return num;
//  }
//  
//  public void selfAdd() {
//      num++;
//  }
//  
    public static void main(String[] args) throws InterruptedException {
        
        
    
        Thread t1 = new Thread("thread A") {
            public void run() {
                System.out.println("start "+this.getName());
                for(int i = 0 ; i < 50 ; i++ ) {
                    //read
                    System.out.println(this.getName()+":read -> "+string);
                    //write
                    string = "A"+i;
                    System.out.println(this.getName()+":write -> "+string);
                }
                    
            }
        };
        
        Thread t2 = new Thread("thread B") {
            public void run() {
                System.out.println("start "+this.getName());
                for(int i = 0 ; i < 50 ; i++ ) {
                    //read
                    System.out.println(this.getName()+":read ->"+string);
                    //write
                    string = "B"+i;
                    System.out.println(this.getName()+":write -> "+string);
                }
            }
        };
        
        t1.start();
        t2.start();
        
        t1.join();
        t2.join();
    }

}

输出:脏,我写出来的多线程真的贼赃

start thread B
thread B:read ->
start thread A
thread B:write -> B0
thread B:read ->B0
thread B:write -> B1
thread B:read ->B1
thread B:write -> B2
thread B:read ->B2
thread B:write -> B3
thread B:read ->B3
thread B:write -> B4
thread B:read ->B4
thread A:read -> B0
thread B:write -> B5
thread B:read ->A0
thread B:write -> B6
thread B:read ->B6
thread B:write -> B7
thread B:read ->B7
thread A:write -> A0
thread A:read -> B8
thread B:write -> B8
thread B:read ->A1
thread A:write -> A1
thread B:write -> B9
thread B:read ->B9
thread B:write -> B10
thread B:read ->B10
thread B:write -> B11
thread B:read ->B11
thread B:write -> B12
thread B:read ->B12
thread B:write -> B13
thread B:read ->B13
thread B:write -> B14
thread B:read ->B14
thread B:write -> B15
thread B:read ->B15
thread B:write -> B16
thread B:read ->B16
thread B:write -> B17
thread B:read ->B17
thread B:write -> B18...

所以说我并不同意volatile保证了可见性这一说法,我只同意他保证了有序性。因为他能保证可见性是在原子性的前提下。

你可能感兴趣的:(JAVA_volatile)