JUC
文章平均质量分 78
期华_
珍惜现在,便是把握未来。
展开
-
可重入锁和不可重入锁 & 简单 Code 演示
在 java 中,synchronized、ReentrantLock 都是可重入锁。结论:当一个线程获取锁后,当再次获取同一把锁时,会默认已经获取了。原创 2020-08-06 22:03:05 · 1438 阅读 · 3 评论 -
ThreadLocal 言简意赅
toc。原创 2020-08-06 22:13:35 · 402 阅读 · 2 评论 -
java多线程:19、J.U.C之并发容器
介绍HashMap是我们用得非常频繁的一个集合,但是它是线程不安全的。并且在多线程环境下,JDK1.7下put操作是有可能产生死循环,不过在JDK1.8的版本中更换了数据插入的顺序,已经解决了这个问题。为了解决该问题,提供了Hashtable和Collections.synchronizedMap(hashMap)两种解决方案,但是这两种方案都是对读写加锁,独占式。一个线程在读时其他线程必须等待,吞吐量较低,性能较为低下。而J.U.C给我们提供了高性能的线程安全HashMap:ConcurrentHas原创 2020-10-20 09:21:33 · 187 阅读 · 0 评论 -
java多线程:18、J.U.C之Semaphore
介绍Semaphore([三迫否])是一个控制访问多个共享资源的计数器,和CountDownLatch一样,其本质上是一个“共享锁”。Semaphore维护了一个信号量许可集。线程可以获取信号量的许可;当信号量中有可用的许可时,线程能获取该许可;否则线程必须等待,直到有可用的许可为止。线程可以释放它所持有的信号量许可,被释放的许可归还到许可集中,可以被其他线程再次获取。举个例子:假设停车场仅有5个停车位,一开始停车场没有车辆,先后到来三辆车,停车场车位够,安排进去停车,然后又来三辆,这原创 2020-10-20 09:19:11 · 146 阅读 · 0 评论 -
java多线程:17、J.U.C之CountDownLatch
介绍CountDownLatch是一个计数的闭锁,作用与CyclicBarrier有点儿相似。在API中是这样描述的:用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,调用await 方法的线程会一直受阻塞。当计数到达零时,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。CountDownLatch:一个或者多个线程等原创 2020-10-20 09:17:36 · 137 阅读 · 0 评论 -
java多线程:16、J.U.C之CyclicBarrier
介绍CyclicBarrier([赛可理可白瑞]):同步屏障,在JDK1.5被引入的一个同步辅助类,在API中是这么介绍的:允许一组线程全部等待彼此达到共同屏障点的同步辅助。 **循环阻塞**在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。 屏障被称为循环,因为它可以在等待的线程被释放之后重新使用。CyclicBarrier好比一扇门,默认情况下关闭状态,堵住了线程执行的道路,直到所有线程都就位,门才打开,让所有线程一起通过。实现分析CyclicBarrier的内部是使用重入锁原创 2020-10-20 09:16:30 · 114 阅读 · 0 评论 -
java多线程:15、J.U.C之Condition
Condition介绍在没有Lock之前,我们使用synchronized来控制同步,配合Object的wait()、notify()系列方法可以实现等待/通知模式。在JDK5后,Java提供了Lock接口,相对于Synchronized而言,Lock提供了条件Condition,对线程的等待、唤醒操作更加详细和灵活。下图是Condition与Object的监视器方法的对比:Condition提供了一系列的方法来对阻塞和唤醒线程:await():造成当前线程在接到信号或被中断之前一直处于等待状原创 2020-10-20 09:15:11 · 120 阅读 · 0 评论 -
java多线程:14、J.U.C之锁
锁的基本概念虽然在前面锁优化的部分已经提到过一些锁的概念,但不完全,这里是对锁的概念补充。1 互斥锁在编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。2 阻塞锁阻塞锁,可以说是让线程进入阻塞状态进行等待,当获得相应的信号(唤醒,时间) 时,才可以进入线程的准备就绪状态,准备就绪状态的所有线程,通过竞争,进入运行状态。3 自旋锁自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循原创 2020-10-20 09:13:58 · 119 阅读 · 0 评论 -
java多线程:13、J.U.C之AQS
AQS简介AQS(AbstractQueuedSynchronizer):队列同步器。它是构建锁或者其他同步组件的基础框架(如ReentrantLock、ReentrantReadWriteLock、Semaphore等),JUC并发包的作者(Doug Lea)期望它能够成为实现大部分同步需求的基础。它是JUC并发包中的核心基础组件。在这里我们只是对AQS进行了解,它只是一个抽象类,但是JUC中的很多组件都是基于这个抽象类,也可以说这个AQS是多数JUC组件的基础。AQS的作用Java的内置锁一直都原创 2020-10-20 09:13:14 · 148 阅读 · 0 评论 -
java多线程:12、J.U.C之Atomic包
atomic包介绍它们的内部都维护者一个对应的基本类型的成员变量value,这个变量是被volatile关键字修饰的,保证多线程环境下看见的是同一个(可见性)。AtomicInteger在进行一些原子操作的时候,依赖Unsafe类里面的CAS方法,原子操作就是通过自旋方式,不断地使用CAS函数进行尝试直到达到自己的目的。除了AtomicInteger类以外还有很多其他的类也有类似的功能,在JUC中有一个包java.util.concurrent.atomic存放原子操作的类,atomic里的类主要包括原创 2020-10-20 09:11:57 · 176 阅读 · 0 评论 -
java多线程:11、JUC之CAS
JUC简介J.U.C 框架是 Java 5 中引入的,而我们最熟悉的线程池机制就在这个包,J.U.C 框架包含的内容有:AbstractQueuedSynchronizer(AQS框架),J.U.C 中实现锁和同步机制的基础;Locks & Condition(锁和条件变量),比 synchronized、wait、notify 更细粒度的锁机制;Executor 框架(线程池、Callable、Future),任务的执行和调度框架;Synchronizers(同步器),主要用于协助线程原创 2020-10-20 09:10:08 · 173 阅读 · 0 评论 -
java多线程:10、锁优化
synchronized是重量级锁,效率不高。但在jdk 1.6中对synchronize的实现进行了各种优化,使得它显得不是那么重了。jdk1.6对锁的实现引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。锁主要存在四中状态,依次是:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态,他们会随着竞争的激烈而逐渐升级。注意锁可以升级不可降级,这种策略是为了提高获得锁和释放锁的效率。1 自旋锁线程的阻塞和唤醒需要CPU从用户态转为核心态,频繁的阻塞和唤醒原创 2020-10-20 09:08:17 · 108 阅读 · 0 评论 -
java多线程:9、内存可见性
内存可见性介绍可见性:一个线程对共享变量值的修改,能够及时的被其他线程看到共享变量:如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量线程 A 与线程 B 之间如要通信的话,必须要经历下面 2 个步骤:首先,线程 A 把本地内存 A 中更新过的共享变量刷新到主内存中去。然后,线程 B 到主内存中去读取线程 A 之前已更新过的共享变量。如上图所示,本地内存 A 和 B 有主内存中共享变量 x 的副本。假设初始时,这三个内存中的 x 值都为 0。线程 A 在执行原创 2020-10-11 16:53:05 · 225 阅读 · 1 评论 -
java多线程:8、内存可见性前置知识
了解Java内存模型JVM内存结构、Java对象模型和Java内存模型,这就是三个截然不同的概念,而这三个概念很容易混淆。这里详细区别一下1 JVM内存结构我们都知道,Java代码是要运行在虚拟机上的,而虚拟机在执行Java程序的过程中会把所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途。其中有些区域随着虚拟机进程的启动而存在,而有些区域则依赖用户线程的启动和结束而建立和销毁。在《Java虚拟机规范(Java SE 8)》中描述了JVM运行时内存区域结构如下(五大区域):各区域功能原创 2020-10-11 16:51:04 · 155 阅读 · 0 评论 -
java多线程:7、多线程并发的3个特性
1、原子性原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行2、可见性可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值其本质是告诉jvm当前变量在本地内存中的值是不确定的,需从主内存中读取。举个简单的例子,看下面这段代码://线程1执行的代码int i = 0;i = 10;//线程2执行的代码j = i;当线程1执行int i = 0 这句时,i的初始值0加载到内存中,然后再执行i = 10,原创 2020-10-11 16:47:45 · 192 阅读 · 0 评论 -
java多线程:6、Join&yield&优先级
1、线程插队join()方法join作用是让其他线程变为等待。thread.Join把指把thread线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。 public static void main(String[] args) { JoinThread joinThread = new JoinThread(); Thread thread1 = new Threa原创 2020-10-11 16:47:10 · 124 阅读 · 0 评论 -
java多线程:5、线程停止
结束线程有以下三种方法:设置退出标志,使线程正常退出。使用interrupt()方法中断线程。使用stop方法强行终止线程(不推荐使用Thread.stop, 这种终止线程运行的方法已经被废弃,使用它们是极端不安全的!)1、使用退出标志一般run()方法执行完,线程就会正常结束,然而,常常有些线程是伺服线程。它们需要长时间的运行,只有在外部某些条件满足的情况下,才能关闭这些线程。使用一个变量来控制循环,例如:最直接的方法就是设一个boolean类型的标志,并通过设置这个标志为true或fals原创 2020-10-11 16:46:38 · 112 阅读 · 0 评论 -
java多线程:4、线程安全
线程安全多个线程在同时运行一段相同的代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的,反之则是线程不安全的。代码实现不安全的线程public class 产生 { public static void main(String[] args) { //创建线程任务对象 Ticket ticket = new Ticket(); //创建三个窗口对象 Thread t1 = ne原创 2020-10-11 16:46:07 · 115 阅读 · 0 评论 -
java多线程:3、守护线程&线程等待
守护线程Java中有两种线程,一种是用户线程,另一种是守护线程。用户线程是指用户自定义创建的线程,主线程停止,用户线程不会停止。守护线程当进程不存在或主线程停止,守护线程也会被停止public class 守护线程 { public static void main(String[] args) { Thread t = new Thread(() -> { String name = Thread.currentThread().getNa原创 2020-10-11 16:45:28 · 173 阅读 · 0 评论 -
java多线程:2、线程状态
线程的五种状态初始状态:new就绪状态:进入就绪状态的四种方式:1、start方法2、阻塞解除3、yield4、jvm将其他线程切换到本地线程运行状态:得到cpu的执行权阻塞状态:进入阻塞状态的四种方式:1、sleep(抱着资源睡觉)2、wait(不占用资源)3、join(线程插队)4、io操作死亡状态:1、线程执行完2、设置标志位、interrupt()、stop()(不推荐)java中线程的状态在java中认为从就绪状态进入运行状态的时间一般都是比较短的,所以合并为原创 2020-10-11 16:44:39 · 85 阅读 · 0 评论 -
java多线程:1、多线程基础
面试:为什么要使用多线程?一个采用了多线程技术的应用程序可以更好地利用系统资源。其主要优势在于充分利用了CPU的空闲时间片,可以用尽可能少的时间来对用户的要求做出响应,使得进程的整体运行效率得到较大提高,同时增强了应用程序的灵活性。更为重要的是,由于同一进程的所有线程是共享同一内存,所以不需要特殊的数据传送机制,不需要建立共享存储区或共享文件,从而使得不同任务之间的协调操作与运行、数据的交互、资源的分配等问题更加易于解决。面试:线程和进程进程:是指一个内存中运行的应用程序,每个进程原创 2020-10-11 16:42:38 · 159 阅读 · 0 评论 -
浅谈Volatile的作用及原理
Volatile我们知道虽然JVM对synchronized做了很多优化,但是它还是一个重量级的锁。而接下来要介绍的volatile则是轻量级的synchronized。如果一个变量使用volatile,则它比使用synchronized的成本更加低,因为它不会引起线程上下文的切换和调度。Java语言规范对volatile的定义如下:Java允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。通俗点讲就是说一个变量如果用volatile修饰了,则Jav原创 2020-09-07 13:40:41 · 205 阅读 · 0 评论