JMM
概念
JMM: Java Memory Model (JAVA 内存模型)。
是Java语言中用于定义多线程并发访问共享内存的规范。它规定了多线程环境下,如何保证共享内存的一致性和可见性,以及如何协调多个线程之间的操作。

主内存和工作内存(本地内存)
JMM将内存划分为主内存和每个线程的工作内存。主内存是所有线程共享的内存,而每个线程都有自己的工作内存。线程可以从主内存中读取数据到工作内存,然后进行操作,最后将结果写回主内存。
进程和线程
进程是操作系统中的一个独立执行单元,它包含了程序代码、数据和系统资源的副本。每个进程都有自己的地址空间,它们之间通常是相互隔离的。
线程是进程内的一个执行单元,多个线程共享同一个进程的地址空间和资源。一个进程可以包含多个线程。
进程是程序运行资源分配(内存)的最小单位;线程是CPU调度的最小单位。
并发和并行
Erlang 之父 Joe Armstrong 用一张5岁小孩都能看懂的图解释了并发与并行的区别。

并发是指应用程序交替执行任务。
并行是指应用程序同时执行不同的任务。
并发的三大特性
并发的三大特性:可见性,原子性,有序性
可见性
可见性是指一个线程修改了共享变量对其他线程是可见的。
实现方式
- volatile关键字
- 内存屏障
- sychronized关键字
- Lock
- final关键字
原子性
原子性是指一个操作不可分割,要么全部执行成功,要么全部失败。
实现方式
- sychronized关键字
- Lock
- CAS
有序性
即程序执行的顺序按照代码的先后顺序执行。
实现方式
-
通过 volatile 关键字保证有序性
-
通过 内存屏障保证有序性
-
通过 synchronized关键字保证有序性
-
通过Lock锁保证有序性
原子操作
- lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。
- unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
- read(读取):作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用
- load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
- use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。
- assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
- store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作。
- write(写入):作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中。

sychronized
sychronized是Java的关键字,用来加锁。可以用于修饰方法和代码块。
synchronized关键字不仅保证可见性,同时也保证了原子性(互斥性)。
public class BankAccount {
private int balance;
public BankAccount(int initialBalance) {
this.balance = initialBalance;
}
//sychronized修饰方法
public synchronized void transfer(int amount) {
if (balance >= amount) {
balance -= amount;
System.out.println("Transfer successful. Remaining balance: " + balance);
} else {
System.out.println("Insufficient funds.");
}
}
public void performOperation(int increment) {
//sychronized修饰代码块
synchronized (this) {
value += increment;
System.out.println("Updated value: " + value);
}
}
}
如上面代码,
第一个synchronized修饰transfer方法,表示只有一个线程执行该方法。
第二个sychronized修饰代码块。表示只有一个线程可以同时进入这个代码块。
volatile
volatile 是 Java 中用于修饰变量的关键字,它具有特殊的语义,主要用于确保多线程环境下对共享变量的可见性和有序性。
Java中的volatile关键字可以保证多线程操作共享变量的可见性以及禁止指令重排序。