多线程
文章平均质量分 96
小饭团~
抱最大的希望,为最大的努力,做最坏的打算。
展开
-
25. 悲观锁 和 乐观锁
悲观锁与乐观锁是管理并发冲突的两种策略。悲观锁假定冲突频繁发生,通过加锁阻止其他事务访问数据,确保数据一致性但可能降低并发性能。乐观锁则假设数据冲突较少,读取时不加锁,更新时验证数据版本,减少锁竞争提高并发度,但在高冲突场景下可能需重试操作。两者各有利弊,适用于不同并发控制需求。原创 2024-06-01 07:28:25 · 786 阅读 · 0 评论 -
24.显式锁-ReentrantLock
显式锁作为Java并发编程领域的一项进阶同步技术,相较于传统的synchronized关键字,在灵活性与控制精细度上实现了显著提升。它在Java的并发编程java.util.concurrent.locks中,通过标准化的Lock接口及其强大实现类——如ReentrantLock,为开发人员构建了一套丰富多维的同步工具集,深度赋能并发控制策略的定制与优化。ReentrantLock等实现不仅沿袭了基本的互斥访问控制,还引入了诸如可重入性、公平性配置、锁中断、以及读写分离等高级特性。原创 2024-05-31 06:42:31 · 868 阅读 · 0 评论 -
23.显式锁-ReentrantLock
想要在并发编程的战场上所向披靡?深入了解ReentrantLock,开启高效同步的新纪元,让你的代码在多线程世界里如虎添翼。点击了解更多,让我们一起探索ReentrantLock那未被完全揭开的神秘面纱!ReentrantLock,作为Java并发包中的一员,是实现锁机制的重量级工具,相较于synchronized关键字,提供了更高的灵活性和可控性。该锁支持公平与非公平两种锁获取模式,允许线程重复获取同一把锁,并要求按相同次数释放,确保了锁的可重入性。原创 2024-05-30 07:27:57 · 934 阅读 · 0 评论 -
22.Volatile原理
Volatile关键字在Java中扮演着确保变量可见性与禁止指令重排序的关键角色,它是实现线程安全轻量级同步的一种方式。通过volatile修饰的变量,任何对其的修改都会立即写回主内存,同时其他线程对这一变量的访问总是能获取到最新值,从而避免了缓存一致性问题。这使得volatile在某些特定场景,如状态标记、双重检查锁定等模式中极为有用。尽管volatile能保证可见性,但并不意味着它能替代所有的同步需求。它不能保证原子性操作,下面我一起来了解一下volatile原理。原创 2024-05-29 06:57:37 · 1113 阅读 · 2 评论 -
显式锁的分类
显式锁作为并发编程中的核心组件,为开发者提供了比内置锁(如synchronized)更灵活的控制手段。从不同维度划分,显式锁展现出多种类型,满足多样化的并发控制需求。首先,可重入锁与不可重入锁区分了锁能否被同一线程多次获取而不引发死锁。悲观锁与乐观锁代表了对并发冲突的不同处理哲学,前者假定冲突普遍存在故提前加锁,后者则假设冲突较少,仅在提交修改时验证数据版本。共享锁与独占锁界定了资源访问模式,前者允许多个读取者共享资源,后者确保每次只有一个访问者。原创 2024-05-26 22:08:30 · 541 阅读 · 0 评论 -
21.Happens-Before原则
本文深入探讨了"Happens-Before"规则的核心概念,列举了六种保证操作间顺序的关键场景,包括程序顺序规则、监视器锁规则、volatile变量规则、线程启动规则、线程终结规则及传递性规则。例如,监视器锁规则确保了对一个锁的解锁操作happens-before于随后对同一锁的加锁操作,这直接关联到synchronized代码块或方法的内存效果,保障了数据的同步更新。原创 2024-05-26 08:47:40 · 758 阅读 · 0 评论 -
20.有序性与内存屏障
对于现在CPU来说,在CPU内核 和 主存之间都具备一个高速缓存,高速缓存主要为了减少CPU内核 和主存之间的交互,在CPU内核进行读操作时,也是先从高速缓存中读取,在CPU内核写的时候,也是先写入高速缓存,最后统一写入主存。读屏障是将高速缓存中相应的数据失效,在指令前插入读屏障,可以让高速缓存中的数据失效,强制重新从主存中加载数据,并且读屏障会告诉CPU和编译器,后于这个屏障的读指令必须后执行,不能对后面的读操作进行指令重排。写屏障的插入不仅会将数据同步到主存,还会阻止编译器和CPU对写操作进行重排序。原创 2024-05-25 04:57:09 · 731 阅读 · 0 评论 -
19.硬件层的MESI协议原理
MESI协议,全称为Modified, Exclusive, Shared, Invalid,是一种用于维护缓存一致性的重要协议,广泛应用于多处理器系统中。该协议确保了每个处理器的高速缓存与主内存中的数据保持一致,通过四个状态来标记缓存行(cache line)的状态:Modified(已修改)、Exclusive(独占)、Shared(共享)和Invalid(无效)。原创 2024-05-24 08:29:44 · 1189 阅读 · 0 评论 -
18.并发编程原子性、可见性、有序性原理
在并发编程的领域里,原子性、有序性和可见性是构建高效、正确并发系统不可或缺的三大基石。本文深入浅出地探讨了这三个核心概念,揭示它们如何共同支撑起多线程环境下程序的可靠执行。原创 2024-05-22 06:47:20 · 811 阅读 · 0 评论 -
17.高并发场景下CAS效率的优化
LongAdder的基本思路就是分散热点,将value值分散到一个数组中,不同线程会命中不同槽中的元素,每个线程只能对自己槽中的那个值进行CAS操作,这样热点就被分散了,冲突的概率就小很多了。LongAdder的实现思路其实和CurrentHashMap中分段使用的原理非常相似,本质上都是不同的线程,在不同的单元上进行操作,减少了线程的竞争,提高了并发的效率。总的来说,LongAdder 的设计思路清晰,将累加操作分解成多个独立的单元,通过分段累加和并行计算提高了在高并发情况下的性能表现。原创 2024-05-16 07:19:47 · 1188 阅读 · 0 评论 -
16.ABA问题
ABA问题是指在并发编程中,由于CAS(比较并交换)操作的特性,可能出现的一种问题。CAS是一种乐观锁机制,用于实现多线程环境下的原子操作。期望值更新值和当前值。CAS操作会比较当前值和期望值,如果相等,则将当前值更新为新值,否则不进行任何操作。CAS操作的局限性导致了ABA问题的出现。并发场景下的共享变量修改:多个线程同时对一个共享变量进行修改和操作。CAS操作的原子性:CAS操作只能检查共享变量当前的值是否和预期值相等,并在相等时才进行更新操作。原创 2024-05-15 12:43:40 · 1411 阅读 · 1 评论 -
15.JUC原子类
基础原子类(以AtomicInteger为例),主要是通过CAS自旋 + volatile相结合的方案实现,既保证了变量操作线程的原子性,有避免了synchronized重量级锁的开销,使得Java程序的效率得到大幅度提升。基础原子类型 只能保证一个变量的原子操作,但是当需要对多个变量操作时,CAS无法保证原子性操作,这个时候可以使用AtomicReference(原子引用类型),保证对象引用的原子性。属性更新原子类是Java并发包提供的一组类,用于原子性地更新对象中的属性值。原创 2024-05-14 08:02:55 · 992 阅读 · 0 评论 -
14.CAS原理
JDK 5 所增加的 JUC(java.util.concurrent)并发包对操作系统的底层的CAS原子操作进行了封装,为上层Java程序提供了CAS操作的APICAS(Compare and Swap)是一种并发编程中的原子操作,用于实现多线程环境下的无锁同步。内存位置(或者说是要操作的变量的引用)、期望值和新值。首先,读取内存位置的当前值,这是期望值。然后,将期望值与内存位置的当前值进行比较。如果相等,则说明内存位置的值没有被其他线程修改,可以进行更新操作。原创 2024-05-13 06:50:36 · 1049 阅读 · 0 评论 -
13.重量级锁原理及其实战
这篇文章深入探讨了重量级锁的核心原理及其在JVM中的实现细节。重量级锁通过监视器来保护临界区代码,确保在任何时刻只有一个线程可以进入临界区执行。文章详细解释了监视器的特点,如同步、协作、信号机制等,并介绍了在JVM中监视器是如何通过ObjectMonitor类来实现的,以及该类的关键属性和作用。其中,_cxq、_WaitSet、_EntryList等队列被用来存放等待获取监视器锁的线程,而_owner变量则记录了当前持有该监视器的线程。通过分析这些细节,读者可以更深入地理解重量级锁的工作原理和实现机制。原创 2024-05-10 07:07:45 · 1107 阅读 · 0 评论 -
12.轻量级锁原理及其实战
引入轻量级锁的主要目的是在多线程环境竞争不激烈的情况下, 通过CAS机制竞争锁减少重量级锁的产生的性能损耗,重量级锁使用了操作系统底层的互斥锁,会导致线程在用户态和核心态之间频繁切换,从而带来较大的性能损耗。因为内置锁对象的Mark Word的结构会有所变化,Mark Word将会出现一个指向锁记录的指针,而不再存在无锁状态下的锁的哈希码等信息,所以必须将这些信息暂存起来,供后面锁释放的时候使用。轻量级锁膨胀是指在使用轻量级锁的过程中,如果锁竞争激烈或者存在其他特定情况,JVM会将轻量级锁膨胀为重量级锁。原创 2024-05-09 07:20:19 · 1286 阅读 · 0 评论 -
11.偏向锁原理及其实战
偏向锁是Java虚拟机(JVM)为了优化无竞争情况下的锁性能而引入的机制。当一个线程获取了对象的锁时,JVM会将该对象标记为偏向锁状态,并记录获取锁的线程ID。在无竞争情况下,线程再次获取锁时无需竞争,直接进入同步代码块,提高程序性能。然而,偏向锁引入了记录线程ID和CAS操作的开销,因此JVM会延迟启用偏向锁。偏向锁并不适用于有竞争的情况,会自动升级为轻量级锁或重量级锁以保证线程的互斥访问和数据一致性。原创 2024-05-08 11:51:56 · 816 阅读 · 0 评论 -
10.Java对象内置结构
这篇文章详细介绍了Java对象的内置结构,分为对象头、对象体和对齐字节三个部分。对象头包括标记字、类指针和数组长度等字段,用于存储对象的元数据和状态信息。对象体则包含实例变量,用于存储对象的属性值。对齐字节则是为了优化内存访问效率而添加的额外字节,确保对象在内存中对齐。文章还介绍了对象结构中核心字段的作用,包括标记字、类指针、数组长度等。最后,通过图示和解释说明了Mark Word的结构信息,以及使用JOL工具查看对象布局的方法。这篇文章总结了Java对象内置结构的关键概念和机制,适合Java开发者深入了解原创 2024-05-07 07:27:06 · 921 阅读 · 0 评论 -
9.Java内置锁的核心原理-Synchronized
本文深入探讨了Java内置锁(Synchronized)的核心原理。首先介绍了内置锁的基本概念,包括互斥性、可重入性、等待与通知机制以及内存可见性。然后详细解释了对象监视器、互斥性、可重入性、等待与通知机制以及内存可见性等方面的实现原理。最后,阐述了使用synchronized关键字修饰代码块或方法时的行为,以及线程在获取锁后执行被保护代码的流程。通过这些内容,读者能够深入理解Java内置锁的工作机制,从而更好地编写线程安全的Java代码。原创 2024-05-06 07:17:25 · 993 阅读 · 2 评论 -
8.Java并发编程—ThreadLocal,TreadLocalMap,InheritableThreadLocal,TransmittableThreadLocal使用指南
本文带深入探讨 ThreadLocal、ThreadLocalMap、InheritableThreadLocal 和 TransmittableThreadLocal 的详细使用。介绍了 ThreadLocal 的作用和原理,并提供了基本使用方法。随后,对 ThreadLocalMap 进行了深度解析,包括内部结构、工作原理和增删改查操作。接着,讨论了 InheritableThreadLocal 在线程继承中的应用和特性,以及 TransmittableThreadLocal 在线程池和异步调用。原创 2024-03-27 23:04:11 · 1056 阅读 · 2 评论 -
7.Java并发编程—掌握线程池的标准创建方式和优雅关闭技巧,提升任务调度效率
本文详细介绍了线程池的标准创建方式和参数设置,包括核心线程数、最大线程数和阻塞队列的选择。同时,探讨了向线程池提交任务的两种方式:execute()和submit()。通过案例演示,展示了如何使用这两种方法来提交任务。此外,文章还介绍了线程池的任务调度流程,包括ThreadFactory的源码解析和自定义简单线程工厂的实现方式。对于任务阻塞队列和线程池的拒绝策略也进行了解析,并提供了优雅关闭线程池的方法。最后,通过测试案例验证了限时等待和等待全部任务执行完毕两种关闭线程池的技巧,帮助读者更好地掌握线程池。原创 2024-03-24 20:21:33 · 1000 阅读 · 1 评论 -
6.Java并发编程—深入剖析Java Executors:探索创建线程的5种神奇方式
本文深入剖析了Java中使用Executors类创建线程的5种方式。这些方式包括newSingleThreadExecutor()、newFixedThreadPool(int nThreads)、newCachedThreadPool()、newScheduledThreadPool(int corePoolSize)和newWorkStealingPool(int parallelism)。每种方式都具有独特的特点和适用场景。通过了解这些线程池的工作原理和适用性,我们可以根据实际需求选择最合适的线程池类原创 2024-03-13 21:58:37 · 459 阅读 · 2 评论 -
5.Java并发编程—JUC线程池架构
Java并发编程中的JUC(Java Util Concurrent)线程池架构是一种强大的工具,用于管理和调度多个线程执行任务。该架构提供了一种高效、可扩展的方式来处理并发任务。JUC线程池架构的核心组件包括线程池Executor、工作线程Worker和任务队列BlockingQueue。Executor是线程池的主要入口,它接收任务并将其提交给线程池进行执行。Worker线程负责执行任务的实际逻辑,通过从任务队列中获取任务并执行。任务队列是一个缓冲区,用于存储待执行的任务。原创 2024-03-12 22:19:31 · 1412 阅读 · 0 评论 -
Java线程的基本操作
线程基本操作包括sleep、interrupted、join、yield等。sleep用于使线程暂停一段时间,通常用于模拟等待或者定时任务。interrupted用于检查线程是否被中断,可以帮助线程处理中断请求。join用于等待线程执行完成,主要用于协调多个线程的执行顺序。yield让出当前线程的执行权,让其他线程有机会执行,有助于提高线程执行的公平性。这些操作都是多线程编程中常用的基本操作,能够帮助程序员控制线程的执行顺序和行为,确保线程之间的协作和同步。原创 2024-03-12 00:14:30 · 1189 阅读 · 0 评论 -
深入理解Java线程执行原理
在学习线程的核心原理之前,我们先来了解一下 线程的调度 和执行在Java中,线程调度与执行是指Java虚拟机(JVM)根据一定的调度算法和优先级来决定哪个线程在特定时刻执行。线程调度是多线程并发执行的关键部分,它决定了线程在CPU上执行的顺序和时间片分配。原创 2024-03-09 10:21:55 · 1355 阅读 · 0 评论 -
Java并发编程-实现多线程的四种方式
在Java中,有四种常见的创建线程的方式:继承Thread类、实现Runnable接口、实现Callable接口配合Future和ExecutorService、以及使用Executor框架。每种方式都有自己的优缺点和适用场景。继承Thread类简单直接,但限制了类的继承层次结构;实现Runnable接口避免了单继承的限制,提高了灵活性;实现Callable接口可以获取任务执行结果和控制线程数量,但相对繁琐;使用Executor框架提供了高度灵活的线程管理和任务调度功能,但需要合理配置以避免资源浪费。选择合原创 2024-03-07 22:04:59 · 1183 阅读 · 0 评论 -
Java并发编程-进程和线程
进程和线程是计算机科学中重要的概念,用于管理程序的执行和资源分配。进程是操作系统中的一个独立执行单位,拥有自己的内存空间和系统资源。每个进程都可以包含一个或多个线程,线程是进程内的实际执行单元,共享相同的内存空间和资源。本文简要介绍了进程和线程的概念、特点以及它们在计算机系统中的作用。进程和线程的使用使得程序能够并发执行,提高了系统的效率和性能。然而,进程和线程的管理也面临着诸多挑战,如资源竞争、死锁等问题。因此,合理地使用和管理进程与线程对于保障系统稳定运行和提升性能至关重要。原创 2024-03-05 21:32:03 · 765 阅读 · 0 评论 -
深入理解Java并发编程中的LockSupport
Java并发编程中的LockSupport类是一个重要的工具,用于线程的阻塞和唤醒操作。相比传统的同步机制,LockSupport提供了更灵活、安全的线程同步方式。其基本概念包括park()和unpark()方法,通过操作系统提供的底层同步机制实现线程的阻塞和唤醒。LockSupport与synchronized、wait/notify相比具有更精细的线程控制能力,支持线程中断,避免了死锁问题。在实际应用中,LockSupport常用于自定义同步器和高性能并发场景,需要注意避免多次调用unpark()方法原创 2024-02-27 23:38:38 · 747 阅读 · 0 评论 -
基于ReentrantLock的Java并发编程探索
并发编程是指在计算机系统中,同时执行多个独立的任务或操作的一种编程方式。在现代计算机系统中,利用多核处理器、分布式系统等技术,实现并发性已经成为常态。提高系统性能:通过并发编程,可以充分利用计算资源,同时执行多个任务,提高系统的吞吐量和响应速度。例如,可以将一个大型任务拆分成多个子任务并行执行,加快整体处理速度。提升用户体验:对于需要实时响应的应用程序,如网络服务器、图形界面程序等,采用并发编程可以避免因单线程阻塞而导致的界面卡顿或响应延迟,提升用户体验。资源利用率提高。原创 2024-02-25 16:37:02 · 1118 阅读 · 0 评论