一、业务逻辑中的并发问题
1. 示例
当存在 一个类中 的 两个方法 同时被 多个线程 执行操作 共享资源 时,需要考虑加锁。
示例如下:
public class LockTest_1 {
private static final Logger log = LoggerFactory.getLogger(LockTest_1.class);
volatile int a = 1;
volatile int b = 1;
public void add() {
log.info("add start");
for (int i = 0; i < 10_0000; i++) {
a++;
b++;
}
log.info("add end");
}
public void compare() {
log.info("compare start");
for (int i = 0; i < 10_0000; i++) {
// a 始终等于 b 吗?
// 比较操作不是原子性的,在字节码层面是会先加载 a 再加载 b 后进行比对大小
// 当加载完a后,到b被加载时 这之间 b可能被add()又++了多次,出现了a < b的情况
if (a < b) {
log.info("a:{},b:{},{}", a, b, a > b);
// 最后的 a > b 始终是 false 吗?
}
}
log.info("compare start");
}
public static void main(String[] args) {
LockTest_1 lockTest_1 = new LockTest_1();
new Thread(() -> lockTest_1.add()).start();
new Thread(() -> lockTest_1.compare()).start();
}
}
输出结果:
2021-05-01 18:31:54.688 [INFO ] [Thread-1] [c.j.test.locktest.LockTest_1 ] compare start
2021-05-01 18:31:54.688 [INFO ] [Thread-0] [c.j.test.locktest.LockTest_1 ] add start
2021-05-01 18:31:54.695 [INFO ] [Thread-1] [c.j.test.locktest.LockTest_1 ] a:390,b:1025,false
2021-05-01 18:31:54.698 [INFO ] [Thread-1] [c.j.test.locktest.LockTest_1 ] a:52277,b:52294,true
2021-05-01 18:31:54.698 [INFO ] [Thread-1] [c.j.test.locktest.LockTest_1 ] a:56056,b:56061,false
2021-05-01 18:31:54.699 [INFO ] [Thread-1] [c.j.test.locktest.LockTest_1 ] a:62865,b:62870,false
2021-05-01 18:31:54.699 [INFO ] [Thread-1] [c.j.test.locktest.LockTest_1 ] a:64628,b:64634,true
2021-05-01 18:31:54.699 [INFO ] [Thread-1] [c.j.test.locktest.LockTest_1 ] a:71524,b:71535,false
2021-05-01 18:31:54.699 [INFO ] [Thread-1] [c.j.test.locktest.LockTest_1 ] a:78008,b:78017,false
2021-05-01 18:31:54.699 [INFO ] [Thread-1] [c.j.test.locktest.LockTest_1 ] a:83293,b:83298,true