![](https://img-blog.csdnimg.cn/20201014180756780.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
多线程与并发
bazhuayu_1203
看书、健身、赚钱、用心爱一个人。
展开
-
synchronized底层加锁原理自己的理解与总结
synchronized加锁实现方式1、在进入加锁代码块时增加一个monitorenter指令,然后针对锁对象关联的monitor累加加锁计数器count,同时标志这个线程加了锁。synchronized是可重入锁,就是可以多次加锁,每加一次,monitor里加锁计数器都加1。2、在离开加锁代码块是增加一个monitorexit指令,然后递减monitor里的加锁计数器,如果加锁计数器递减为0,就标志当前线程不持有锁,也就是释放了锁。3、然后wait和notify关键字的实现也是依托于monitor实原创 2020-11-29 11:47:00 · 388 阅读 · 0 评论 -
volatile底层实现可见性、有序性的理解与总结
并发编程中常常绕不开原子性、可见性与有序性的讨论。本文的标题中提到了volatile对可见性和有序性的保证,唯独没有提原子性,是因为volatile只有在特定场景下才会保证原子性,像volatile++ 这种复合的操作是不保证原子性的,当然对任意单个volatile变量的读/写是具有原子性的。什么是原子性原子(atomic)本意是不能被进一步分割的最小粒子,而原子操作意为不可被中断的一个或者一系列操作。文章开头说volatile只有特定场景下才会保证原子性,这个特定场景就是在32位处理器里,对do原创 2020-11-28 20:23:33 · 208 阅读 · 0 评论 -
happens-before自己的理解与总结
我们知道Java代码在编译后会变成Java字节码,类加载器把Java字节码加载到JVM里,JVM执行字节码,最终会转化成汇编指令在cpu上执行。在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排序,看下图。1、编译器优化重排序,什么意思呢,就是编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。2、指令级并行重排序,它的意思是如果不存在数据依赖性,处理器可以改变语句对应机器码指令顺序,多条指令重叠执行。3、内存系统重排序,它的意思是现代处理器都有高速缓存和写缓冲区,这样看原创 2020-11-28 10:38:54 · 169 阅读 · 0 评论 -
CPU是如何通过缓存一致性MESI协议解决可见性的
上一篇文章,介绍了CPU的一些关键组件、高速缓存、写缓冲区和无效队列等,文章结尾留下了一个问题,就是CPU为了性能引入的写缓冲区和无效队列后可能会导致线程之间不可见问题。想了解硬件层面导致的可见性问题的朋友可以看下关于CPU几个不得不知的概念,文末有说明。底层解决方案CPU通过缓存一致性MESI(修改、独占、共享、无效)协议,这个MESI协议实际上有很多种不同的实现,具体的实现机制要靠具体底层的系统如何实现。比如有一种实现,就是一个处理器将另外一个处理器的高速缓存中的更新后的数据拿到自己高速缓存来更新一原创 2020-11-27 09:23:57 · 379 阅读 · 0 评论 -
关于CPU的几个概念自己的理解
现代处理器为了提高性能都引入了高速缓存、写缓冲区、无效队列(有些处理器比如X86没有)等东西,本文将和大家一起来看看这些东西究竟是个啥玩意,能解决什么问题。高速缓存由于对现代处理器的运行速度要求越来越高,为了提高性能,硬件设计者就引入了高速缓存的概念。处理器有了高速缓存后,就不直接跟内存发生读写操作,而是读写高速缓存里数据。写缓冲区现代处理器都有自己的写缓冲区,来临时保存写入内存中的数据,要注意的是写缓冲区只对自己的处理器可见。在介绍写缓冲区之前,必需先要了解MESI(缓存一致性)协议。现代处理器都原创 2020-11-24 22:43:09 · 325 阅读 · 0 评论 -
Java内存模型自己的理解
面试题:i++是线程安全的吗有一个经典的面试题:i++是线程安全的吗。对于这个问题,稍微懂些答题技巧的朋友就知道回答只要是多线程执行是不安全的。那肯定是线程不安全的呀,线程安全你还问什么,手动狗头!关键是要要分析出面试官问这个问题是为了考察你什么知识点,面试官是想知道你对Java内存模型熟不熟悉。Java内存模型ava的并发采用的是共享内存模型,在共享内存的并发模型里,线程之间共享程序的公共状态,通过写-读内存中的公共状态进行隐形通信。这句话是摘自《Java并发编程的艺术》。下面我来一张图来讲下我自己原创 2020-11-23 22:11:10 · 84 阅读 · 0 评论 -
线程池的核心参数及工作原理
JDK中线程池的类是ThreadPoolExecutor,如果不借助Executors.newFixedThreadPool(3)等方式创建,可以用构建函数来创建线程池,它的代码是这样的,public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable原创 2020-11-22 21:39:56 · 1357 阅读 · 0 评论