29.并发编程之happens-before规则

[TOC]前言Happens-Before规则主要有两个作用:一是解决数据竞争问题;二是为开发人员提供足够强的内存可见性。一、概述1.1 数据竞争数据竞争就是指并发条件下的状态属性不同步而引发的读写不一致问题。现假设有两个线程A、B要对内存中的同一个变量进行访问,线程A要对这个变量执行写操作,线程B要对这个变量执行读操作,两个操作是同时进行的,此时若不加以限制,线程B读操作所得到的结果就有两种可能,且结果是不可预测的,这并不是开发人员希望看到的结果,在JMM(Java内存模型)设计之初就考虑到了这个问题,必须人为的指定读/写操作的执行顺序,Happens-Before规则应运而生。1.2...

Java 2022-11-02 PM 966℃ 0条

28.并发编程之DCL问题

[TOC]一、概述定义:如果一个类始终只能创建一个实例,那么这个类被称为单例类,这种设计模式被称为单例模式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。注意:单例类只能有一个实例。单例类必须自己创建自己的唯一实例。单例类必须给所有其他对象提供这一实例。更详细的可以看之前推送的文章:单例模式简介二、懒汉式单例为了在多线程环境下保护懒汉式,需要加上 synchronized 锁public final class Singleton { private Singleton...

Java 2022-11-01 PM 1235℃ 0条

27.并发编程之volatile原理

[TOC]一、内存屏障内存屏障(Memory Barrier)又称内存栅栏,是一个CPU指令,它的作用有两个:一是保证特定操作的执行顺序;二是保证某些变量的内存可见性(利用该特性实现volatile的内存可见性)。由于编译器和处理器都能执行指令重排优化。如果在指令间插入一条Memory Barrier则会告诉编译器和CPU,不管什么指令都不能和这条Memory Barrier指令重排序,也就是说通过插入内存屏障禁止在内存屏障前后的指令执行重排序优化。Memory Barrier的另外一个作用是强制刷出各种CPU的缓存数据,因此任何CPU上的线程都能读取到这些数据的最新版本。总之,vola...

Java 2022-10-31 PM 1199℃ 0条

26.并发编程之有序性介绍

[TOC]一、基本概念对于一个线程的执行代码而言,我们总是习惯性认为代码的执行总是从上到下,有序执行。但为了提升性能,编译器和处理器通常会对指令序列进行重新排序。Java规范规定JVM线程内部维持顺序化语义,即只要程序的最终结果与它顺序化执行的结果一致,那么指令的执行顺序可以与代码顺序不一致,此过程叫指令的重排序。指令重排序类型(1)编译器优化的重排序:编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。(2)指令级并行的重排序:现代处理器采用了指令级并行技术(ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。(3)内存系统的重排...

Java 2022-10-30 PM 1370℃ 0条

25.并发编程之Balking模式

[TOC]一、volatile改进两阶段终止模式1.1 示例import lombok.extern.slf4j.Slf4j; /** * Created by lilinchao * Date 2022/10/29 * Description volatile实现两阶段终止 */ @Slf4j(topic = "c.Test09") public class Test09 { public static void main(String[] args) throws InterruptedException { TwoPhaseTe...

Java 2022-10-29 AM 976℃ 0条

24.并发编程之可见性介绍

[TOC]一、Java内存模型JMM即Java Memory Model,它定义了主存、工作内存抽象概念,底层对应着CPU寄存器、缓存、硬件内存、CPU指令优化等。JMM 体现在以下几个方面原子性:保证指令不会受到线程上下文切换的影响可见性:保证指令不会受 cpu 缓存的影响有序性:保证指令不会受 cpu 指令并行优化的影响简单的说,JMM 定义了一套在多线程读写共享数据时(成员变量、数组)时,对数据的可见性、有序性和原子性的规则和保障。二、不可见性导致的问题示例main 线程对 run 变量的修改对于 t 线程不可见,导致了 t 线程无法停止import lombok.extern.s...

Java 2022-10-27 PM 1237℃ 0条

23.同步模式之顺序控制

[TOC]一、固定运行顺序题目:有两个线程分别输出1和2,要求输出结果必须先2后1打印1.1 wait notify 版import lombok.extern.slf4j.Slf4j; /** * @author lilinchao * @date 2022-10-26 * @description 固定运行顺序 wait notify实现 * 必须先2后1打印 **/ @Slf4j(topic = "c.Test01") public class Test01 { // 用来同步的对象 static final Object lock...

Java 2022-10-26 PM 1253℃ 0条

22.并发编程之ReentrantLock简介

[TOC]一、概述ReentrantLock是一种基于AQS框架的应用实现,是JDK中的一种线程并发访问的同步手段,它的功能类似于synchronized是一种互斥锁,可以保证线程安全。相对于 synchronized 它具备如下特点:可中断synchronized锁加上去不能中断,a线程应用锁,b线程不能取消掉它可以设置超时时间synchronized它去获取锁时,如果对方持有锁,那么它就会进入entryList一直等待下去。而ReentrantLock可以设置超时时间,规定时间内如果获取不到锁,就放弃锁。可以设置为公平锁防止线程饥饿的情况,即先到先得。如果争抢的人比较多,则可能会发生...

Java 2022-10-25 PM 1311℃ 0条

21.并发编程之活跃性分析

[TOC]一、死锁死锁产生的四个必要条件互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放。不剥夺条件:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时由自己释放。环路等待条件:在发生死锁时,必然存在一个进程–资源的环形链。死锁示例有这样的情况:一个线程需要同时获取多把锁,这时就容易发生死锁t1 线程获得A对象锁,接下来想获取 B对象的锁t2 线程获得B对象锁,接下来想获取 A对象的锁import lombok.extern.slf4j.Slf4j; import static ...

Java 2022-10-24 PM 1210℃ 0条

20.并发编程之多把锁问题

[TOC]一、背景介绍现在有一个房子,在房子中有卧室和书房:书房可以用来学习卧室可以用来睡觉但是学习和睡觉两件事不冲突,不过学习和学习会出现冲突,睡觉和睡觉之间存在冲突。二、示例当整个房子只有一把锁时现在t1线程要获取锁进房间学习,t2线程要进房间睡觉import lombok.extern.slf4j.Slf4j; /** * Created by lilinchao * Date 2022/10/23 * Description 多把锁 */ @Slf4j(topic = "c.Test03") public class Test03 { pub...

Java 2022-10-23 PM 1262℃ 0条