
java并发编程之美
文章平均质量分 84
光阴不负卿
进击的程序员
展开
-
java8新增StampedLock详解
1、StampedLock概述StampedLock是并发包里面JDK8版本新增的一个锁,该锁提供了三种模式的读写控制,当调用获取锁的系列函数时,会返回一个long型的变量,我们称之为戳记(stamp),这个戳记代表了锁的状态。其中try系列获取锁的函数,当获取锁失败后会返回为0的stamp值。当调用释放锁和转换锁的方法时需要传入获取锁时返回的stamp值。StampedLock提供的三种读写模式的锁分别如下:写锁writeLock:是一个排它锁或者独占锁,某时只有一个线程可以获取该锁,当一个线原创 2021-01-18 21:17:05 · 2964 阅读 · 2 评论 -
信号量Semaphore详解
Semaphore信号量是java中的一个同步器,与CountDownLatch和CyclicBarrier不同的是,它内部的计数器是递增的,并且在一开始初始化Semaphore时可以指定一个初始值,但是并不需要知道需要同步的线程个数,而是在需要同步的地方调用acquire方法时指定需要同步的线程个数。1、案例1在主线程中开启两个子线程让它们执行,等所有子线程执行完毕后主线程再继续向下运行。import java.util.concurrent.ExecutorService;import原创 2021-01-18 20:17:22 · 4120 阅读 · 2 评论 -
回环屏障CyclicBarrier详解
CountDownLatch的计数器是一次性的,也就是等到计数器值变为0后,再调用CountDownLatch的await和countdown方法都会立刻返回,这就起不到线程同步的效果了。CyclicBarrier可以让一组线程全部达到一个状态后再全部同时执行。这里之所以叫做回环是因为所有等待线程执完毕,并重置CyclicBarrier的状态后它可以被重用。之所以叫做屏障是因为线程调用await方法后就会被阻塞,这个阻塞点就成为屏障点,等所有线程都调用了await方法后,线程就会冲破屏障,继续向下运行。原创 2021-01-18 17:35:13 · 412 阅读 · 0 评论 -
CountDownLatch详解
1、案例介绍在日常开发中经常会遇到需要在线程中开启多个线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后再进行汇总的场景。在CountDownLatch出现之前一般都使用线程的join()方法来实现这一点,但是join()方法不够灵活,不能够满足不同场景的需要。使用CountDownLatch的代码如下:public class JoinCountDownLatch { // 创建一个CountDownLatch实例 private static volatile Co原创 2021-01-18 11:33:25 · 530 阅读 · 1 评论 -
ScheduledThreadPoolExecutor原理详解
ScheduledThreadPoolExecutor是一个可以在指定一定延迟时间后或者定时进行任务调度执行的线程池。ScheduledThreadPoolExecutor继承了ThreadPoolExecutor并实现了ScheduledExecutorService接口。线程池队列是DelayedWorkQueue,其和DelayedQueue类似,是一个延迟队列。三个重要方法:schedule(Runnable command, long delay, TimeUnit unit)方法原创 2021-01-16 20:48:35 · 1102 阅读 · 0 评论 -
Java线程池详解(面试)
1、线程池简介线程池主要解决两个问题:一是当执行大量异步任务时线程池能够提供较好的性能。在不使用线程池时,每当需要执行异步任务时直接new一个线程来运行,而线程的创建和销毁是需要开销的。线程池里面的线程是可复用的,不需要每次执行异步任务时都重新创建和销毁线程。二是线程池提供了一种资源限制和管理手段,比如可以限制线程的个数,动态新增线程等。2、java中提供的线程池Executors类提供了四种不同的线程池:newCachedThreadPool,newFixedThreadPool,newSch原创 2021-01-16 17:54:01 · 217 阅读 · 0 评论 -
ReentrantReadWriteLock原理详解
解决线程安全问题使用ReentrantLock就可以,但是ReentrantLock是独占锁,某时只有一个线程可以获取该锁,而实际中会有写少读多的场景,显然ReentrantLock满足不了这个需求,所以ReentrantReadWriteLock应运而生。ReentrantReadWriteLock采用读写分离的策略,允许多个线程可以同时获取读锁。读写锁内部维护了两个锁,一个用于读操作,一个用于写操作。所有ReadWriteLock实现都必须保证writeLock操作的内存同步效果也要保持与相关r原创 2021-01-16 15:08:37 · 3520 阅读 · 0 评论 -
ReentrantLock原理详解
ReentrantLock简介:ReentrantLock是可重入的独占锁,同时只能有一个线程可以获取该锁,其他获取该锁的线程会被阻塞而被放入该锁的AQS阻塞队列里面。ReentrantLock主要利用CAS+AQS队列来实现。它支持公平锁和非公平锁,两者的实现类似。从类图可以看到,ReentrantLock最终还是使用AQS来实现的,并且根据参数来决定其内部是一个公平还是非公平锁,默认是非公平锁。获取锁:1、void lock()方法当一个线程调用该方法时,说明该线程希望获取该原创 2021-01-15 20:56:15 · 3916 阅读 · 0 评论 -
AQS面试详解
1、AQS原理AQS(AbstractQueuedSynchronizer)抽象同步队列。是除了java自带的synchronized关键字之外的锁机制。它是实现同步器的基础组件,并发包中锁的底层就是使用AQS实现的。AQS类图如下:原创 2021-01-15 19:30:27 · 1005 阅读 · 0 评论 -
java LockSupport类详解
1、LockSupport类简介LockSupport类,是JUC包中的一个工具类,是用来创建锁和其他同步类的基本线程阻塞原语。LockSupport类的核心方法有两个:park()和unpark(),其中park()方法用来阻塞当前调用线程,unpark()方法用于唤醒指定线程。这其实和Object类的wait()和singal()方法有些类似,但是LockSupport的这两种方法从语义上将比Object类的方法更清晰,而且可以针对指定线程进行阻塞和唤醒。LockSupport类使用了一种名原创 2021-01-15 17:11:02 · 1827 阅读 · 0 评论 -
java CopyOnWriteArrayList详解
Java并发包中的并发list只有CopyOnWriteArrayList。CopyOnWriteArrayList是一个线程安全的ArrayList,对其进行的修改操作都是在底层的一个复制数组(快照)上进行的,也就是使用了写时复制策略。写时复制(CopyOnWrite,简称COW)思想是计算机程序涉及领域中的一种优化策略。其核心思想是,如果多个调用者(Callers)同时要求相同的资源(如内存或者磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者视图修改资源内容时,系统才会真正原创 2021-01-15 15:59:18 · 4271 阅读 · 0 评论 -
Java原子类:AtomicLong、LongAdder、LongAccumulator详解
JUC包提供了一系列的原子性操作类,这些类都是使用非阻塞算法CAS实现的,相比使用锁实现原子性操作,这在性能上有很大的提高。1、AtomicLongJUC并发包中包含有AtomicInteger、AtomicLong和AtomicBoolean等原子性操作类,它们的原理类似。AtomicLong是原子性递增或者递减类,其内部使用Unsafe来实现。多线程使用AtomicLong统计0的个数:// 统计0的个数public class Atomic { // 创建Long型原子计数原创 2021-01-12 20:06:46 · 1652 阅读 · 0 评论 -
Java中ThreadLocalRandom类原理剖析
1、概述ThreadLocalRandom类是JDK7在JUC包下新增的随机数生成器,它弥补了Random类在多线程下的缺陷。2、Random类及其局限性// java.util.Random的使用方法public class RandomTest { public static void main(String[] args) { // 创建一个默认种子的随机数生成器 Random random = new Random(); //原创 2021-01-12 16:48:37 · 625 阅读 · 0 评论 -
java中的锁详解
1、概述锁像synchronized同步块一样,是一种线程同步机制,但比java中的synchronized同步块更复杂。在java5之前锁是由synchronized同步块实现的,所以不能完全摆脱synchronized关键字。自Java5开始,java.util.concurrent.locks包中包含了一些锁的实现,因此你不用去实现自己的锁了。但是仍然需要了解一些锁的机制。2、乐观锁与悲观锁悲观锁是指对数据被外界修改持保守态度,任务数据很容易就会被其他线程修改,所以在数据被处理前先对数原创 2021-01-12 15:40:54 · 269 阅读 · 0 评论 -
Java伪共享详解
1、什么是伪共享在Cache内部是按行存储的,其中每一行称为一个Cache行。Cache行是Cache与主内存进行数据交换的单位,Cache行的大小一般为2的幂次数字节。当CPU访问某个变量时,首先会去看CPU Cache内是否有该变量,如果有则直接从中获取,否则就直接去主内存里面获取该变量,然后把该变量所在 内存区域的一个Cache行大小的内存复制到Cache中。由于存放到Cache行的是内存块而不是单个变量,所以可能会把多个变量存放到一个Cache行中。当多个线程同时修改一个缓存行里面的多个原创 2021-01-11 22:10:58 · 363 阅读 · 3 评论 -
java:CAS、ABA问题详解
1、java中的原子性操作所谓原子性操作,是指执行一系列操作时,这些操作要么全部执行,要么全部不执行,不存在只执行其中一部分的情况。2、CAS方法CAS即Compare and Swap,其是JDK提供的非阻塞原子性操作,它通过硬件保证了比较-更新操作的原子性。CAS有四个操作数,分别为:对象内存地址、对象中的变量的偏移量、变量预期值和新的值。其操作含义为:如果对象obj中内存偏移量为valueOffset的变量为expect,则使用新的值update替换旧的值expect。也就是说,更新一个变原创 2021-01-11 21:36:39 · 416 阅读 · 0 评论 -
java共享变量的内存可见性问题详解
1、并发和并行并发是指同一时间段内多个任务同时都在执行,并且都没有执行结束,而并行是在说单位时间内多个任务同时在执行。并发任务强调在一个时间段内同时执行,而一个时间段由多个单位时间累计而成,所以说并发的多个任务在单位时间内不一定同时在执行。在单CPU时代多任务都是并发执行的,这是因为单个CPU同时只能执行一个任务。在单CPU时代,多任务是共享一个CPU的,当一个任务占用CPU运行时,其他任务就会被挂起,当占用CPU的任务时间片用完后,会把CPU让给其他任务来使用。2、共享资源所谓共享资源,就原创 2021-01-11 20:24:22 · 1341 阅读 · 1 评论 -
java ThreadLocal用法详解
1、ThreadLocal简介在涉及到多线程需要共享变量的时候,容易出现并发问题,特别是在多个线程需要对一个共享变量进行写入时。为了保证线程安全,一般使用者在访问共享变量时需要进行适当的同步。同步的措施一般是加锁,是得在每个时刻只能有一个线程访问该变量,好处就是便于编码,缺点在于增加了线程间的竞争,降低了效率;第二个是使用ThreadLocal。如果说synchronized是以“时间换空间”,那么ThreadLocal就是以“空间换时间”,因为ThreadLocal的原理就是:对于要在线程间共享的变量原创 2021-01-10 18:49:14 · 2883 阅读 · 2 评论 -
java线程中断和死锁详解
1、线程中断:java中的线程中断是一种线程间的协作模式,通过设置线程的中断标志并不能直接终止该线程的执行,而是被终端的线程根据中断状态自行处理。void interrupt()方法:中断线程,例如,当线程A运行时,线程B可以调用线程A的interrupt()方法来设置线程A的中断标志为true并立即返回。设置标志仅仅是设置标志,线程A实际并没有被中断,它会继续执行下去。如果线程A因为调用了wait系列函数、join方法或者sleep方法而被阻塞挂起,这时候若线程B调用线程A的interrupt()原创 2021-01-10 16:15:26 · 511 阅读 · 0 评论 -
java线程详解
1、线程的概念线程是进程中的一个实体,线程本身是不会独立存在的。进程是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,线程则是进程的一个执行路径,一个进程中至少有一个线程,进程中的多个线程共享进程的资源。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。操作系统再分配资源时是把资源分配给进程的,但是CPU资源比较特殊,它是被分配到线程的,因为真正要占用CPU运行的是线程,所以说线程是CPU分配的基本单位。在Java中,当我们启动main函数时其实就启动了一个JVM的原创 2021-01-09 22:05:45 · 774 阅读 · 0 评论