简单记录一下使用场景,通过aop切面实现一个ip检验拦截的功能,如果ip是白名单就允许在逻辑方法执行完成后存入日志信息表,ip拦截要在方法执行之前,也就是切面的doBefore()方法内,日志的新增要在切面的after()内,当时遇到一个before中已经抛出一场了,但是after还是执行的问题,所有采用volatile关键字修饰一个变量,来控制方法执行。
volatile关键字的作用:保证了变量的可见性(visibility)。被volatile关键字修饰的变量,如果值发生了变更,其他线程立马可见,避免出现脏读的现象。如以下代码片段,isShutDown被置为true后,doWork方法仍有执行。如用volatile修饰isShutDown变量,可避免此问题。
1.没有被修饰的方法示例
public class VolatileTest3 {
static class Work {
boolean isShutDown = false;
void shutdown() {
isShutDown = true;
System.out.println("shutdown!");
}
void doWork() {
while (!isShutDown) {
System.out.println("doWork");
}
}
}
public static void main(String[] args) {
Work work = new Work();
new Thread(work::doWork).start();
new Thread(work::doWork).start();
new Thread(work::doWork).start();
new Thread(work::shutdown).start();
new Thread(work::doWork).start();
new Thread(work::doWork).start();
new Thread(work::doWork).start();
}
}
2.被修饰后的方法示例
public class VolatileTest {
static class A {
int a = 0;
volatile boolean flag = false;
void writer() {
a = 1; //1
flag = true; //2
System.out.println("write");
}
void reader() {
if (flag) { //3
int i = a; //4
System.out.println("read true");
System.out.println("i is :" + i);
} else {
int i = a;
System.out.println("read false");
System.out.println("i is :" + i);
}
}
}
public static void main(String[] args) {
A aaa = new A();
new Thread(() -> aaa.reader()).start();
new Thread(() -> aaa.writer()).start();
}
}
自己尝试一下,可以看出结果,如果还是不明白可以百度volatile 关键字的作用