做水果的网站,企业网站模板用哪个,装修公司全包项目,wordpress fonts.googleapi目录
原子性
如何保证原子性
可见性
如何保证可见性
有序性
如何保证有序性
Java内存模型(JMM内存模型)
Java内存模型的一些关键概念#xff1a;
主内存与工作内存交互协议
Java内存模型通过以下手段来确保多线程程序的正确性#xff1a;
锁机制
volatile
volat…目录
原子性
如何保证原子性
可见性
如何保证可见性
有序性
如何保证有序性
Java内存模型(JMM内存模型)
Java内存模型的一些关键概念
主内存与工作内存交互协议
Java内存模型通过以下手段来确保多线程程序的正确性
锁机制
volatile
volatile禁止指令重排序 Happens-Before 并发三大特性
原子性、可见性、有序性
原子性 原子性是指一个操作是不可中断的。一个原子操作是一个不可分割的整体要么全部执行成功要么全部不执行。在多线程环境下当多个线程访问共享变量时如果其中一个线程在执行某个操作其他线程不能同时执行该操作。
public class AtomicTest {private static volatile int counter 0;public static void main(String[] args) {for (int i 0; i 10; i) {Thread thread new Thread(() - {for (int j 0; j 10000; j) {//synchronized (AtomicTest.class) {counter;// }}});thread.start();}try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(counter);}
} 正常执行后counter变量的值远远大于预期10000加synchronized后counter变量为10000
如何保证原子性 1. 通过synchronized关键字保证原子性 2. 通过 Lock锁保证原子性 3. 通过 CAS保证原子性 可见性 可见性是指当一个线程修改了共享变量的值时其他线程能够立即看到这个修改。在多线程环境下由于线程之间的缓存机制一个线程对共享变量的修改可能不会立即被其他线程看到。 public class VisibilityExample {private static boolean stop false;public static void main(String[] args) {// 线程1修改共享变量Thread thread1 new Thread(() - {while (!stop) {// do something}System.out.println(Thread 1 finished);});// 线程2修改共享变量Thread thread2 new Thread(() - {stop true;System.out.println(Thread 2 set stop to true);});// 启动线程1thread1.start();// 稍等片刻try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// 启动线程2thread2.start();}
}在以上代码中两个线程分别运行并且共享一个stop变量。线程1在一个循环中检查stop变量是否为false而线程2在启动后将stop变量设置为true。然而由于没有同步机制线程1可能不会立即看到线程2对stop变量的修改导致线程1一直在循环中无法退出。
private static volatile boolean stop false;通过给stop变量增加volatile修饰即可保证可见性。
如何保证可见性 通过volatile 关键字保证可见性 通过内存屏障保证可见性 通过synchronized 关键字保证可见性 通过Lock锁保证可见性 有序性 有序性是指程序执行的顺序按照代码的先后顺序执行。在多线程环境下由于指令重排序等优化有时候线程执行的顺序可能与代码的顺序不一致。
public class ReOrderTest {private static int x 0, y 0;private static int a 0, b 0;public static void main(String[] args) throws InterruptedException {int i0;while (true) {i;x 0;y 0;a 0;b 0;Thread thread1 new Thread(new Runnable() {Overridepublic void run() {//用于调整两个线程的执行顺序shortWait(20000);a 1; x b; }});Thread thread2 new Thread(new Runnable() {Overridepublic void run() {b 1;y a;}});thread1.start();thread2.start();thread1.join();thread2.join();System.out.println(第 i 次 x , y ));if (x0y0){break;}}}public static void shortWait(long interval){long start System.nanoTime();long end;do{end System.nanoTime();}while(start interval end);}
}
执行结果x,y出现了0,0的结果程序终止。出现这种结果有可能是重排序导致的。
如何保证有序性 通过volatile 关键字保证有序性 通过内存屏障保证有序性 通过synchronized关键字保证有序性 通过Lock锁保证有序性 Java内存模型(JMM内存模型) Java内存模型Java Memory ModelJMM是Java程序中多线程并发访问共享变量时对内存操作行为的一种规范。它定义了在多线程环境中线程如何与主内存和工作内存交互以确保并发程序的正确性。 Java内存模型的一些关键概念
1. 主内存Main Memory 主内存是所有线程共享的内存区域包含所有的共享变量。所有的线程都可以访问主内存。 2. 工作内存Working Memory 每个线程有自己的工作内存存储了该线程使用到的变量的副本。线程对变量的所有操作都在工作内存中进行不直接读写主内存。 3. 共享变量 多个线程之间可以共享的变量例如类的静态变量或实例变量。 4. 原子性Atomicity 单个的读/写操作是原子的即要么完成要么不开始。 5. 可见性Visibility 当一个线程修改了共享变量的值其他线程应该能够立即看到这个变化。 6. 有序性Ordering 程序执行的顺序与代码中的顺序一致。
主内存与工作内存交互协议
从工 作内存同步到主内存之间的实现细节Java内存模型定义了以下八种原子操作来完成lock锁定:作用于主内存的变量把一个变量标识为一条线程独占状态。unlock解锁:作用于主内存变量把一个处于锁定状态的变量释放出来释放后的变量才可以被其他线程锁 定。read读取:作用于主内存变量把一个变量值从主内存传输到线程的工作内存中以便随后的load动作使用load载入:作用于工作内存的变量它把read操作从主内存中得到的变量值放入工作内存的变量副本中。use使用:作用于工作内存的变量把工作内存中的一个变量值传递给执行引擎每当虚拟机遇到一个需要 使用变量的值的字节码指令时将会执行这个操作。assign赋值:作用于工作内存的变量它把一个从执行引擎接收到的值赋值给工作内存的变量每当虚拟机 遇到一个给变量赋值的字节码指令时执行这个操作。store存储:作用于工作内存的变量把工作内存中的一个变量的值传送到主内存中以便随后的write的操 作。write写入:作用于主内存的变量它把store操作从工作内存中得到的变量的值放入主内存的变量中。 Java内存模型通过以下手段来确保多线程程序的正确性
1. 锁机制 使用synchronized关键字或显式锁来保护共享数据确保在同一时刻只有一个线程可以访问临界区。 2. volatile关键字 用于修饰共享变量保证可见性。对一个volatile变量的写操作将立即刷新到主内存而读操作将从主内存中加载最新的值。 3. final关键字 被final修饰的字段在构造函数结束之前就已经对其他线程可见。 4. Happens-Before关系 JMM定义了Happens-Before的规则确保在某个操作之前的操作对其可见。
锁机制
1. 当线程获取锁时JMM会把该线程对应的本地内存置为无效。 2. 当线程释放锁时JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。 synchronized关键字的作用是确保多个线程访问共享资源时的互斥性和可见性。在获取锁之前线程 会将共享变量的最新值从主内存中读取到线程本地的缓存中释放锁时会将修改后的共享变量的值刷 新到主内存中以保证可见性。
volatile
1. 当写一个volatile变量时JMM会把该线程对应的本地内存中的共享变量值刷新到主内存。 2. 当读一个volatile变量时JMM会把该线程对应的本地内存置为无效线程接下来将从主内存中读取共享变量。
volatile禁止指令重排序 Happens-Before Happens-Before是Java内存模型Java Memory ModelJMM中一个重要的概念用于规定多线程程序中操作之间的执行顺序和可见性关系。这个概念确保了在程序中对共享变量的操作是按照一定顺序执行的以避免出现不确定的结果和数据竞争问题。 如果操作A在操作B之前发生在之前happens-before那么操作A对于操作B来说必定是可见的而且操作A的效果将被操作B看到。
Happens-Before部分关系规则
1. 程序顺序规则Program Order Rule 在一个线程中操作按照程序代码的先后顺序执行。 2. 锁定规则Lock Rule 释放锁的操作Happens-Before于后续对同一锁的加锁操作。 3. volatile变量规则Volatile Variable Rule 对volatile变量的写操作Happens-Before于后续对这个变量的读操作。 4. 传递性Transitivity 如果操作A Happens-Before于操作B且操作B Happens-Before于操作C那么操作A Happens-Before于操作C。 5. 线程启动规则Thread Start Rule 线程的启动操作Happens-Before于该线程的任何操作。 6. 线程终止规则Thread Termination Rule 线程的所有操作Happens-Before于其他线程检测到该线程已经终止。