文章目录
JVM运行时数据区
详见Java程序运行原理分析:https://blog.csdn.net/maxleader/article/details/104098513
从内存结构到内存模型
多线程中的问题
- 所见非所得;
- 肉眼无法检测程序准确性;
- 不同的运行平台有不同的表现;
- 错误很难重现;
工作内存缓存
指令重排序
Java内存模型含义
Shared Variables共享变量描述
线程操作的定义
程序顺序:如果一个程序没有数据竞争,那么程序所有执行看起来顺序都一致;
本规范只涉及线程间的操作;
对于同步的规则定义
Happens-before先行发生原则
volatile关键字
使用volatile代码示例
import java.util.concurrent.TimeUnit;
// 1、 jre/bin/server 放置hsdis动态链接库
// 测试代码 将运行模式设置为-server, 变成死循环 。 没加默认就是client模式,就是正常(可见性问题)
// 2、 通过设置JVM的参数,打印出jit编译的内容 (这里说的编译非class文件),通过可视化工具jitwatch进行查看
// -server -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:+LogCompilation -XX:LogFile=jit.log
// 关闭jit优化-Djava.compiler=NONE
public class VisibilityDemo1 {
// 状态标识 (不用缓存)
private volatile boolean flag = true;
// 源码 -> 字节码class
// JVM 转化为 操作系统能够执行的代码 (JIT Just In Time Compiler 编译器 )(JVM -- client , --server)
public static void main(String[] args) throws InterruptedException {
VisibilityDemo1 demo1 = new VisibilityDemo1();
new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
// class -> 运行时jit编译 -> 汇编指令 -> 重排序
while (demo1.flag) { // 指令重排序
i++;
}
System.out.println(i);
}
}).start();
TimeUnit.SECONDS.sleep(2);
// 设置is为false,使上面的线程结束while循环
demo1.flag = false;
System.out.println("被置为false了.");
}
}
使用synchronized代码示例
import java.util.concurrent.TimeUnit;
public class VisibilityDemo2 {
// 状态标识
private static boolean is = true;
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (VisibilityDemo1.is) {
synchronized (this) {
i++;
}
}
System.out.println(i);
}
}).start();
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 设置is为false,使上面的线程结束while循环
VisibilityDemo2.is = false;
System.out.println("被置为false了.");
}
}
final在JVM中的处理
final代码示例
public class FinalDemo {
public static final String a = "hello tony";
public static void main(String[] args) {
}
}
// 官方示例,可能会读取到y的值为0
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3 肯定是3
int j = f.y; // could see 0 可能看到0
}
}
}
// 官方示例,new A().f() 可能返回 -1, 0, or 1.
class A {
final int x;
A() {
x = 1;
}
int f() {
return d(this, this);
}
int d(A a1, A a2) {
int i = a1.x;
g(a1);
int j = a2.x;
return j - i;
}
static void g(A a) {
// uses reflection to change a.x to 2
// 使用反射技术修改A.x为2
}
}
Word tearing字节处理
Word tearing代码示例
// https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4
// 官方提供的示例,检查有没有WordTearing情况
public class WordTearingDemo extends Thread {
static final int LENGTH = 8;
static final int ITERS = 1000000;
static byte[] counts = new byte[LENGTH];
static Thread[] threads = new Thread[LENGTH];
final int id;
WordTearingDemo(int i) {
id = i;
}
@Override
public void run() {
byte v = 0;
for (int i = 0; i < ITERS; i++) {
byte v2 = counts[id];
if (v != v2) {
System.err.println("Word-Tearing found: " +
"counts[" + id + "] = " + v2 +
", should be " + v);
return;
}
v++;
counts[id] = v;
}
}
public static void main(String[] args) {
for (int i = 0; i < LENGTH; ++i)
(threads[i] = new WordTearingDemo(i)).start();
}
}