static int x;static Object m = new Object();new Thread(()->{synchronized(m) {x = 10;}},"t1").start();new Thread(()->{synchronized(m) {System.out.println(x);}},"t2").start();
- 线程结束前对变量的写 , 对其它线程得知它结束后的读可见(比如其它线程调用 t1.isAlive() 或t1.join()等待它结束)
static int x;Thread t1 = new Thread(()->{ x = 10;},"t1");t1.start();t1.join();System.out.println(x);
- 线程 t1 打断 t2(interrupt)前对变量的写 , 对于其他线程得知 t2 被打断后对变量的读可见
static int x;public static void main(String[] args) {Thread t2 = new Thread(()->{while(true) {if(Thread.currentThread().isInterrupted()) {System.out.println(x);break;}}},"t2");t2.start();new Thread(()->{try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}x = 10;t2.interrupt();},"t1").start();while(!t2.isInterrupted()) {Thread.yield();}System.out.println(x);}
- 对变量默认值(0 , false , null)的写 , 对其它线程对该变量的读可见
- 具有传递性 , 如果 x hb-> y 并且 y hb-> z 那么有 x hb-> z
乐观锁与悲观锁简介我们首先分别简单介绍一下乐观锁和悲观锁:
- 乐观锁的思想:最乐观的估计 , 不怕别的线程来修改共享变量 , 就算改了也没关系 , 我继续重试即可 。
- 悲观锁的思想:最悲观的估计 , 得防着其它线程来修改共享变量 , 针对共享数据直接上锁 , 只有我解锁后你们才能抢夺
- 乐观锁用于竞争不激烈且为多核CPU的情况 , 因为其实乐观锁的不断尝试需要cpu处理并且也会消耗一定内存
- 悲观锁用于竞争激烈需要抢夺资源的情况下 , 我们直接停止其他操作可以减少其他不必要的内耗
- CAS 即 Compare and Swap , 它体现的一种乐观锁的思想
// 需要不断尝试while(true) {int 旧值 = 共享变量 ; // 比如拿到了当前值 0int 结果 = 旧值 + 1; // 在旧值 0 的基础上增加 1 , 正确结果是 1/*这时候如果别的线程把共享变量改成了 5 , 本线程的正确结果 1 就作废了 , 这时候compareAndSwap 返回 false , 重新尝试 , 直到:compareAndSwap 返回 true , 表示我本线程做修改的同时 , 别的线程没有干扰*/if( compareAndSwap ( 旧值, 结果 )) {// 成功 , 退出循环}}
悲观锁实现乐观锁的实现是采用synchronized:- synchronized体现的是一种悲观锁的思想
package cn.itcast.jvm.t4.avo;// 我们进行操作时 , 直接上锁 , 不允许其他进程涉及!public class Demo4_1 {// 这里的i应该被多线程共用 , 设为静态变量static int i = 0;// 这里是Obj对象 , 我们设置它为锁 , 注意两个线程中的synchronized所对应的锁应该是同一个对象(锁)static Object obj = new Object();public static void main(String[] args) throws InterruptedException {// 采用synchronized设置锁实现原子性 , 这样i++操作就会完整进行Thread t1 = new Thread(() -> {synchronized (obj) {for (int j = 0; j < 50000; j++) {i++;}}});Thread t2 = new Thread(() -> {// 采用synchronized设置锁实现原子性 , 这样i--操作就会完整进行synchronized (obj) {for (int j = 0; j < 50000; j++) {i--;}}});t1.start();t2.start();t1.join();t2.join();System.out.println(i);}}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Linux学习环境搭建流程
- Archlinux + Dwm 配置流程
- 关于入门深度学习mnist数据集前向计算的记录
- 四十 Java开发学习----MyBatisPlus入门案例与简介
- jvm双亲委派机制详解
- FHE学习笔记 #2 多项式环
- django-environ学习
- 万字详解JVM,让你一文吃透
- 论文笔记 - GRAD-MATCH: A Gradient Matching Based Data Subset Selection For Efficient Learning
- MFC 学习笔记