
JUC
另一花生
竹杖芒鞋轻胜马,一蓑烟雨任平生
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
Synchronized如何保证原子性 可见性 有序性
原子性:枷锁和释放锁,ObjectMonitor;可见性:加了Load屏障和Store屏障,释放锁flush数据,枷锁会refresh数据;有序性:Acquire屏障和Release屏障,保证同步代码内部的指令可以重排序,但是同步代码内部的指令和外面的指令是不能重排;...原创 2020-10-25 16:11:26 · 1397 阅读 · 1 评论 -
使用锁的一些注意事项
第一,使用 synchronized 加锁虽然简单,但我们首先要弄清楚共享资源是类还是实例级别的、会被哪些线程操作,synchronized 关联的锁对象或方法又是什么范围的。第二,加锁尽可能要考虑粒度和场景,锁保护的代码意味着无法进行多线程操作。对于Web 类型的天然多线程项目,对方法进行大范围加锁会显著降级并发能力,要考虑尽可能地只为必要的代码块加锁,降低锁的粒度;而对于要求超高性能的业务,还要细化考虑锁的读写场景,以及悲观优先还是乐观优先,尽可能针对明确场景精细化加锁方案,可以在适当的场景下考虑使原创 2020-09-29 20:33:22 · 748 阅读 · 0 评论 -
volatile相关知识总结
有volatile变量修饰的共享变量进行写操作的手会多出第二行汇编代码,Lock前缀指令在多核处理器下会引发两件事情;1.强当前处理器缓存行的诗句歇会到系统内存;2.这个歇会内存的操作会使得在其他CPU里缓存了该内存地址的数据无效;为了提高处理速度,处理器不直接合内存进行通信,而是先将系统内存的数据读到内部缓存(L1 L2等)后再进行操作,但操作完不知道何时回写到内存若声明了volatile变量进行写操作,JVM就会向处理器发送一条Lock前缀的指令,将这个变量所在缓存行的数据写回到系统内存原创 2020-09-13 18:01:44 · 173 阅读 · 0 评论 -
异步编程之Future那堆事
有三种 submit。这三种按照提交任务的类型来算分为两个类型。 提交执行 Runnable 类型的任务 提交执行 Callable 类型的任务 他们都是返回Future类型看一下 Callable 类型的任务是怎么回事;注意这个方法,一会会对比到;接下来再说说 submit 的任务为 Runable 类型的情况① 的方法扔进去一个 Runable 的任务,返回一个 Future,而这个返回的 Future ,相当于是返回了一个null。Threa...原创 2020-08-15 17:07:23 · 2065 阅读 · 0 评论 -
线程池源码解析三
/** * Executes the given task sometime in the future. The task * may execute in a new thread or in an existing pooled thread. * * If the task cannot be submitted for execution, either because this * executor has been shutdow.原创 2020-07-28 16:05:38 · 578 阅读 · 0 评论 -
线程池源码总结二
ThreadPoolExecutor几种构造器// Public constructors and methods /** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters and default thread factory and rejected execution handler. * It may be more convenient to原创 2020-07-12 19:29:26 · 304 阅读 · 0 评论 -
线程池源码总结一
ThreadPoolExecutor实现的顶层接口是Executor,顶层接口Executor提供了一种思想:将任务提交和任务执行进行解耦。用户无需关注如何创建线程,如何调度线程来执行任务,用户只需提供Runnable对象,将任务的运行逻辑提交到执行器(Executor)中,由Executor框架完成线程的调配和任务的执行部分。public interface Executor { void execute(Runnable command);} ...原创 2020-07-08 23:00:30 · 431 阅读 · 0 评论 -
wait notify原理
Owner 线程发现条件不满足,调用 wait 方法,即可进入 WaitSet 变为 WAITING 状态BLOCKED 和 WAITING 的线程都处于阻塞状态,不占用 CPU 时间片BLOCKED 线程会在 Owner 线程释放锁时唤醒WAITING 线程会在 Owner 线程调用 notify 或 notifyAll 时唤醒,但唤醒后并不意味者立刻获得锁,仍需进入EntryList 重新竞争参考文章:死磕重量级锁原理...原创 2020-06-14 15:02:06 · 570 阅读 · 0 评论 -
偏向锁撤销
撤销-其他线程使用对象当有其他线程使用偏向锁对象时,会将偏向锁升级为轻量级锁private static void test2() throws InterruptedException { Dog d = new Dog(); Thread t1 = new Thread(() -> { synchronized (d) { log.debug(ClassLayout.parseInstance(d).toPrintableSimpl原创 2020-06-14 11:15:22 · 2149 阅读 · 5 评论 -
偏向锁状态
一个对象创建时,如果开启了偏向锁(默认开启),那么对象创建后,markword值为0x05即最后3位101,这时它的Thread,epoch,age都为0 偏向锁默认是延迟的,不会在程序启动时立即生效,如果想避免延迟,可以加VM参数-xx:BiaseLockingStartupDelay=0来禁用延迟 如果没有开启偏向锁,那么对象创建后,markword值为0x01即最后3位位001,这时它的hashcode,age,都为0,第一次用到hashcode时才会赋值...原创 2020-06-14 00:58:20 · 934 阅读 · 2 评论 -
偏向锁
轻量级锁在没有竞争时,(就自己这个线程),每次重入仍然执行CAS操作.Java6中引入了偏向锁来做进一步优化;只有第一次使用CAS将线程ID设置到对象的Mark Word头,之后发现这个线程ID是自己的就表示没有竞争,不用重新CAS,以后只要不发生竞争,这个对象就归该线程所有例如:static final Object obj = new Object();public static void m1(){ synchronized(obj){ // 同步块 A原创 2020-06-14 00:45:59 · 264 阅读 · 0 评论 -
自旋优化过程注意事项
重量级锁竞争的时候,还可以使用自旋来进行优化,如果当前线程是自旋成功(即这时候将锁线程已经退出了同步块,释放了锁),这时当前线程就可以避免阻塞.在Java6之后自旋锁是自适应的,比如对象刚刚的一次自旋操作成功过,那么认为这次自旋成功的可能性会高,就多自旋几次;反之,就少自旋甚至不自旋,总之,比较智能。 自旋会占用CPU时间,单核 CPU自旋就是浪费,多核CPU自旋才能发挥优势 Java7之后不能控制是否开启自旋功能...原创 2020-06-14 00:30:20 · 486 阅读 · 0 评论 -
锁膨胀过程
如果在尝试加轻量级锁的过程中,CAS操作无法成功,这时一种情况就是有其他线程为此对象加上了轻量级锁(有竞争),这时候需要进行锁膨胀,将轻量级锁变为重量级锁。static Object obj = new Object();public static void method1(){ synchronized(obj){ // 同步块 }}当Thread-1进行轻量级加锁时,Thread-0已经对该对象加了轻量级锁这时Thread-1加轻量级锁失败,进入.原创 2020-06-14 00:18:26 · 1623 阅读 · 0 评论 -
轻量级锁概念以及相关知识点
轻量级锁使用场景:如果一个对象虽然有多线程访问,但多线程访问的时间是错开的(也就是没有竞争),那么可以使用轻量级锁来优化.轻量级锁对使用者是透明的,语法依然是synchronizedstatic final Object obj = new Object();public static void method1(){ synchronized(obj){ // 同步块A method2(); }}public static void met原创 2020-06-14 00:03:54 · 952 阅读 · 0 评论 -
线程安全分析-局部变量-暴露引用
class ThreadSafe { public void method1(int loopNumber){ ArrayList<Object> list = new ArrayList<>(); for (int i = 0; i < loopNumber; i++) { method2(list); method3(list); } } privat.原创 2020-06-09 13:53:22 · 643 阅读 · 0 评论 -
线程运行原理-栈帧图解
public class TestFrames { public static void main(String[] args) { method1(10); } private static void method1(int x){ int y = x + 1; Object m = method2(); System.out.println(m); } private static Object.原创 2020-06-07 19:17:46 · 811 阅读 · 0 评论 -
浅析Java 线程池实例代码
线程池的优点:1.重用线程池中的线程,减少因对象创建,销毁所带来的性能开销;2.能有效的控制线程的最大并发数,提高系统资源利用率,同时避免过多的资源竞争,避免堵塞;3.能够多线程进行简单的管理,使线程的使用简单、高效。线程池框架Executorjava中的线程池是通过Executor框架实现的,Executor 框架包括类:Executor,Executors,ExecutorService,ThreadPoolExecutor ,Callable和Future、FutureTask的使转载 2020-06-05 16:37:41 · 309 阅读 · 0 评论 -
支持生产阻塞的Java线程池
通常来说,生产任务的速度要大于消费的速度。一个细节问题是,队列长度,以及如何匹配生产和消费的速度。一个典型的生产者-消费者模型如下 在并发环境下利用J.U.C提供的Queue实现可以很方便地保证生产和消费过程中的线程安全。这里需要注意的是,Queue必须设置初始容量,防止生产者生产过快导致队列长度暴涨,最终触发OutOfMemory。 对于一般的生产快于消费的情况。当队列已满时,我们并不希望有任何任务被忽略或得不到执行,此时生产者可以等待片刻再提交任务,更好的做法是...转载 2020-06-02 10:03:38 · 271 阅读 · 0 评论 -
java线程池的常规使用
在实际开发过程中,在线程池使用过程中可能会遇到各方面的故障,如线程池阻塞,无法提交新任务等。如果你想监控某一个线程池的执行状态,线程池执行类 ThreadPoolExecutor 也给出了相关的 API, 能实时获取线程池的当前活动线程数、正在排队中的线程数、已经执行完成的线程数、总线程数等。总线程数 = 排队线程数 + 活动线程数 + 执行完成的线程数。线程池使用示例:private static ExecutorService es = new ThreadPoolExecutor(5转载 2020-05-31 21:07:32 · 2866 阅读 · 1 评论 -
线程池参数设置冷门知识点
初始化线程池时可以预先创建线程吗?prestartAllCoreThreads初始化线程池时是可以预先创建线程的,初始化线程池后,再调用prestartAllCoreThreads()方法,即可预先创建corePoolSize数量的核心线程public int prestartAllCoreThreads() { int n = 0; while (addWorker(null, true)) ++n; return n; }转载 2020-05-28 10:09:27 · 1208 阅读 · 1 评论 -
002_重拾多线程之多线程并发级别
并发级别:多线程之间的并发必须受到控制。根据控制并发的策略,我们可以把并发的级别进行分类,大致上可以分为阻塞、无饥饿、无障碍、无锁、无等待几种。1.阻塞(blocking) 一个线程是阻塞的,那么在其他线程释放资源之前,当前线程无法继续执行。当我们使用synchronized关键字,或者重入锁时,我们得到的就是阻塞的线程。 无论是synchronized ...原创 2018-12-15 22:31:04 · 408 阅读 · 0 评论