Table of contents
Purpose
It is convenient for subsequent review by yourself, and it is also a record of learning.
resource
A learning video about high-frequency interview questions at Station B
How to understand thread safety
Reference: What is thread safety
3 aspects to consider in thread safety
visibility
One thread modifies the shared variable, another thread can see the latest result
orderliness
The code in a thread is executed in the order in which it was written, without the influence of instruction rearrangement
atomicity
Multiple lines of code in one thread run as a whole, during which no other thread's code can jump into the queue. There is no impact of thread switching.
Sample code verification
volatile does not guarantee atomicity
/**
* volatile原子性例子: 不能保证原子性
* <p>
* 调试需要拆解"balance -= 5;" 使用Debug模式复现
*
* @author xiaozhengN [email protected]
* @since 2022-11-19 18:09:41
**/
@Slf4j
public class AddAndSubtract {
static volatile int balance = 10;
private static void subtract() {
balance -= 5;
}
private static void add() {
balance += 5;
}
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(2);
new Thread(() -> {
subtract();
latch.countDown();
}).start();
new Thread(() -> {
add();
latch.countDown();
}).start();
latch.await();
log.info("共享变量balance: {}", balance);
}
}
volatile guarantees visibility
/**
* volatile 可见性例子
*
* -Xint
*
* @author xiaozhengN [email protected]
* @since 2022-11-19 17:36:20
**/
@Slf4j
public class ForeverLoop {
// 共享变量, 控制 foo() 循环次数
static volatile boolean isStop = false;
public static void main(String[] args) {
new Thread(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
log.error("", e);
}
isStop = true;
log.info("修改共享变量成功: isStop: {}", isStop);
}).start();
new Thread(() -> {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
log.error("", e);
}
log.info("从主内存中获取共享变量, isStop: {}", isStop);
}).start();
foo();
}
static void foo() {
int i = 0;
while (!isStop) {
i++;
}
log.info("foo方法已结束, 循环次数为: {}", i);
}
}
volatile sets the memory barrier to ensure orderliness (difficult to understand)
/**
* volatile 有序性例子
* <p>
* 没有测试成功, 报错: Unrecognized VM option 'StressCCP'
* java -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation -jar jcstress.jar -t main.daily.Reordering.Case1
* D:\17-JDKS\jdk-16.0.1\bin\java -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation -jar jcstress.jar -t main.daily.Reordering.Case1
*
* @author xiaozhengN [email protected]
* @since 2022-11-19 18:27:03
**/
public class Reordering {
@JCStressTest
@Outcome(id = {
"0, 0", "1, 1", "0, 1"}, expect = Expect.ACCEPTABLE, desc = "可接受的值")
@Outcome(id = "1, 0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "感兴趣的值(发生指令重排)")
@State
public static class Case1 {
int x;
int y;
@Actor
public void actor1() {
x = 1;
y = 1;
}
@Actor
public void actor2(II_Result result) {
result.r1 = y;
result.r2 = x;
}
}
@JCStressTest
@Outcome(id = {
"0, 0", "1, 1", "0, 1"}, expect = Expect.ACCEPTABLE, desc = "可接受的值")
@Outcome(id = "1, 0", expect = Expect.FORBIDDEN, desc = "被禁止的值")
@State
public static class Case2 {
int x;
volatile int y;
@Actor
public void actor1() {
x = 1;
y = 1;
}
@Actor
public void actor2(II_Result result) {
result.r1 = y;
result.r2 = x;
}
}
@JCStressTest
@Outcome(id = {
"0, 0", "1, 1", "0, 1"}, expect = Expect.ACCEPTABLE, desc = "可接受的值")
@Outcome(id = "1, 0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "感兴趣的值(发生指令重排)")
@State
public static class Case3 {
volatile int x;
int y;
@Actor
public void actor1() {
x = 1;
y = 1;
}
@Actor
public void actor2(II_Result result) {
result.r1 = y;
result.r2 = x;
}
}
}