
Java并发编程
文章平均质量分 69
深入探索并发世界
洞玄之
不积跬步,无以至千里
展开
-
(四)互斥锁下:如何用一把锁保护多个资源?
受保护资源和锁之间合理的关联关系应该是 N:1 的关系。当我们要保护多个资源时,首先要区分这些资源是否存在关联关系。保护没有关联关系的多个资源在现实世界里,球场的座位和电影院的座位就是没有关联关系的,这种场景非常容易解决,那就是球赛有球赛的门票,电影院有电影院的门票,各自管理各自的。(门票:锁 ;座位:资源)**对应到编程领域,例如,银行业务中有针对账户余额(余额是一种资源)的取款操作,也有针对账户密码(**密码也是一种资源)的更改操作,我们可以为账户余额和账户密码分配不同的锁来解决并发问题,这个还是翻译 2020-12-06 22:52:22 · 640 阅读 · 0 评论 -
(三)互斥锁(上):解决原子性问题
原子性一个或者多个操作在 CPU 执行的过程中不被中断的特性,称为“原子性”原子性问题如何解决?原子性问题的源头是线程切换,如果能够禁用线程切换那不就能解决这个问题了吗?而操作系统做线程切换是依赖 CPU 中断的,所以禁止 CPU 发生中断就能够禁止线程切换。在早期单核 CPU 时代,这个方案的确是可行的,但是并不适合多核场景。这里我们以 32 位 CPU 上执行 long 型变量的写操作为例来说明这个问题,long 型变量是 64 位,在 32 位 CPU 上执行写操作会被拆分成两次写操作(写高原创 2020-11-25 00:06:00 · 522 阅读 · 0 评论 -
(二)java 内存模型:解决可见性和有序性问题
什么是 Java 内存模型?我们知道,导致可见性的原因是缓存,导致有序性的原因是编译优化,那解决可见性、有序性最直接的办法就是禁用缓存和编译优化,但是这样问题虽然解决了,我们程序的性能可就堪忧了。合理的方案应该是按需禁用缓存以及编译优化。所以,为了解决可见性和有序性问题,只需要提供给程序员按需禁用缓存和编译优化的方法即可。Java 内存模型本质上可以理解为,Java 内存模型规范了 JVM 如何提供按需禁用缓存和编译优化的方法。具体来说,这些方法包括 volatile、synchronized 和 fi原创 2020-11-22 22:58:57 · 204 阅读 · 0 评论 -
(一)并发编程带来的可见性/原子性/有序性问题
缓存导致的可见性问题可见性:一个线程对共享变量的修改,另外一个线程能够立刻看到,称之为可见性多核时代,每颗 CPU 都有自己的缓存,当多个线程在不同的 CPU 上执行时,这些线程操作的是不同的 CPU 缓存。比如下图中,线程 A 操作的是 CPU-1 上的缓存,而线程 B 操作的是 CPU-2 上的缓存,很明显,这个时候线程 A 对变量 V 的操作对于线程 B 而言就不具备可见性了。多核 CPU 的缓存与内存关系图 下面我们再用一段代码来验证一下多核场景下的可见性问题。下面的代码,每执行一次 a原创 2020-11-08 23:13:20 · 265 阅读 · 0 评论 -
三个线程交替顺序打印ABC
题目描述建立三个线程A、B、C,A线程打印10次字母A,B线程打印10次字母B,C线程打印10次字母C,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印。5种方法使用synchronized, wait和notifyAll使用Lock->ReentrantLock 和 state标志使用Lock->ReentrantLock 和Con...原创 2018-09-10 21:01:38 · 26830 阅读 · 29 评论 -
多线程下 i++和++i 操作如何保证线程安全
volatile解决的是多线程间共享变量的可见性问题,而保证不了多线程间共享变量原子性问题。对于多线程的i++,++i,依然还是会存在多线程问题,volatile是无法解决的.如下:使用一个线程i++,另一个i–,最终得到的结果不为0。原因是i++和++i并非原子操作,我们通过javaP查看字节码,会发现void f1() { i++; } 的字节码‘如下: void ...原创 2018-09-10 10:38:12 · 12599 阅读 · 6 评论 -
乐观锁和悲观锁 以及 乐观锁的一种实现方式-CAS
强推:https://www.cnblogs.com/qjjazry/p/6581568.html悲观锁总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。再比如Java里面的同步原语synchronized关键...原创 2018-09-05 15:05:03 · 1668 阅读 · 1 评论 -
锁优化
为了在线程之间更高效的共享数据,以及解决竞争问题,从而提高程序的执行效率,实现了各种锁优化技术。锁的优化策略编码过程中可采取的锁优化的思路有以下几种:1、减少锁持有时间 例如:对一个方法加锁,不如对方法中需要同步的几行代码加锁;2、减小锁粒度例如:ConcurrentHashMap采取对segment加锁而不是整个map加锁,后来又对node加锁,提高并发性;3、锁分离...原创 2018-09-05 14:30:42 · 829 阅读 · 0 评论 -
线程安全实现的方法
线程安全实现的方法主要有:互斥同步、非阻塞同步(CAS)、线程局部变量(threadLocal)、wait和notify、java.util.concurrent并发工具包、volatile保证变量的线程安全等。1、互斥同步(悲观并发)2、非阻塞法同步(基于冲突检测的乐观并发) 主要使用的就是CAS+失败重试3、无同步方案 将变量保存在本地线程中,就不会出现多个线程并发的错误了。 ...原创 2018-09-04 23:50:26 · 657 阅读 · 0 评论 -
Java对象头
一、对象的内存布局 HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header)->3字宽 Mark Word :存储对象的hashcode或锁信息(1字宽)Class Metadata Address:类型指针(1字宽): 即是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。Array Length:数组长度(1字宽...原创 2018-09-04 22:46:03 · 1732 阅读 · 0 评论 -
Java并发编程:深入剖析ThreadLocal
https://www.cnblogs.com/dolphin0520/p/3920407.htmlThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。 先了解一下ThreadLocal类提供的几个方法:public T ge...原创 2018-09-04 21:02:23 · 166 阅读 · 0 评论 -
解析Volitile关键字
https://www.cnblogs.com/dolphin0520/p/3920373.htmlvolatile的原理和实现机制 前面讲述了源于volatile关键字的一些使用,下面我们来探讨一下volatile到底如何保证可见性和禁止指令重排序的。 下面这段话摘自《深入理解Java虚拟机》: “观察加入volatile关键字和没有加入volatile关键字时所生成的...转载 2018-09-04 15:33:09 · 1369 阅读 · 0 评论 -
synchronized 和Lock区别
区别如下: 来源: lock是一个接口,而synchronized是java的一个关键字,synchronized是内置的语言实现;异常是否释放锁: synchronized在发生异常时候会自动释放占有的锁,因此不会出现死锁;而lock发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生。(所以最好将同步代码块用try catch包起来,finall...转载 2018-09-04 14:49:36 · 122073 阅读 · 24 评论 -
两个线程一个打印1,一个打印2,要求循环打印121212
方法1: 分析问题 两个线程,可以想到的是多线程编程,共享变量,数据等,设想先让一个线程打印1,然后处于等待(wait)状态,接着另一个线程打印2,然后唤醒(notify)线程1,线程2再进入等待(wait)状态,线程1被唤醒后接着打印1,依次循环输出即可代码public class ThreadPrint { static final Object object=new ...转载 2018-07-29 23:13:54 · 1272 阅读 · 2 评论