volatile关键字的使用场景
可见性与互斥性
volatitle无法解决互斥性产生的问题。当一个成员变量被volatile修饰,那么使用该变量的线程都将从主存中读取这个变量,并且该变量不会给各个线程分配不同的拷贝。但是,如果各个线程需要对此变量做修改,是不能使用这个变量的,因为此关键字依然无法让各个线程访问唯一的变量。主存中的拷贝依然还是拷贝。只有处理不需要对这个变量做操作,即可见性问题的情况下,才使用这个关键字。
举两个例子
1.使用该变量的情况:
public static void main(String[] args) throws InterruptedException {
class Thread1 extends Thread{
private volatile boolean stopped;
public void run(){
while(!stopped){
System.out.println("running");
}
System.out.println("stop");
}
void stopT(){
stopped = true;
}
}
Thread1 t1 = new Thread1();
t1.start();
Thread.sleep(1000);
t1.stopT();
}
子线程t1需要根据主线程执行情况进行停止,只要能搞读取到stopped变量值即可,volatile修饰后的值,正好能够从内存中读取该变量,完美解决子线程停止问题。
2.不能用该变量的情况
class Thread1 extends Thread{
private volatile int i = 0;
public void run(){
while(i<50){
System.out.println(Thread.currentThread().getName()+":"+(++i));
}
}
}
Thread1 t1 = new Thread1();
t1.start();
Thread1 t2= new Thread1();
t2.start();
输出情况
Thread-1:1
Thread-0:1
Thread-1:2
Thread-0:2
Thread-1:3
Thread-0:3
Thread-0:4
Thread-1:4
Thread-1:5
Thread-0:5
Thread-1:6
Thread-0:6
Thread-1:7
Thread-0:7
Thread-1:8
Thread-1:9
Thread-1:10
Thread-1:11
Thread-0:8
Thread-0:9
Thread-0:10
Thread-0:11
Thread-0:12
Thread-1:12
Thread-0:13
Thread-0:14
Thread-0:15
Thread-0:16
Thread-0:17
Thread-1:13
Thread-1:14
Thread-1:15
Thread-1:16
Thread-1:17
Thread-0:18
Thread-0:19
Thread-0:20
Thread-0:21
Thread-0:22
Thread-0:23
Thread-0:24
Thread-0:25
Thread-0:26
Thread-1:18
Thread-0:27
Thread-0:28
Thread-0:29
Thread-0:30
Thread-0:31
Thread-1:19
Thread-0:32
Thread-0:33
Thread-0:34
Thread-1:20
Thread-1:21
Thread-1:22
Thread-1:23
Thread-1:24
Thread-1:25
Thread-1:26
Thread-1:27
Thread-0:35
Thread-0:36
Thread-1:28
Thread-1:29
Thread-1:30
Thread-1:31
Thread-0:37
Thread-1:32
Thread-0:38
Thread-1:33
Thread-0:39
Thread-1:34
Thread-0:40
Thread-1:35
Thread-0:41
Thread-1:36
Thread-0:42
Thread-1:37
Thread-0:43
Thread-1:38
Thread-0:44
Thread-1:39
Thread-0:45
Thread-1:40
Thread-0:46
Thread-0:47
Thread-0:48
Thread-0:49
Thread-0:50
Thread-1:41
Thread-1:42
Thread-1:43
Thread-1:44
Thread-1:45
Thread-1:46
Thread-1:47
Thread-1:48
Thread-1:49
Thread-1:50
结果出现很多重复值,很明显不符合预期。由此也可说明,当存在互斥性问题时,不能使用volatile关键字。反例中我们需要对i值作出自增操作,出现很多重复值说明了各个线程在写入值时无法做到同步,对于这种情况下的多线程操作,建议使用synchronized。