当一个共享变量被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保证了可见性这一说法,我只同意他保证了有序性。因为他能保证可见性是在原子性的前提下。
网友评论