一.介绍 volatile保证共享变量的"可见性".可见性指的是当一个线程修改变量时,另一个线程能读到这个修改的值. 这里就要提出几个问题. 问题1:为什么一个线程修改时,另一个线程可能会"看不见"? 问题2:这种可见性是如何实现的? 二.问题1 变量为何"不可见" 回答:是由于缓存导致的可见性问题 2.1 为什么要引入缓存? 是为了解决性能问题.CPU的处理速度远远快于内存的读取速度(CPU与内存之间的瓶颈也叫"冯诺依曼瓶颈"…
volatile两大作用 1.保证内存可见性 2.防止指令重排 此外需注意volatile并不保证操作的原子性. (一)内存可见性 1 概念 JVM内存模型:主内存和线程独立的工作内存 Java内存模型规定,对于多个线程共享的变量,存储在主内存当中,每个线程都有自己独立的工作内存(比如CPU的寄存器),线程只能访问自己的工作内存,不可以访问其它线程的工作内存. 工作内存中保存了主内存共享变量的副本,线程要操作这些共享变量,只能通过操作工作内存中的副本来实现,操作完毕之后再同步回到主内存当中. 如…
一. 产生并发Bug的源头 可见性 缓存导致的可见性问题 原子性 线程切换带来的原子性问题 有序性 编译优化带来的有序性问题 上面讲到了 volatile 与可见性,本章再主要讲下原子性.有序性与Happens-Before规则. 二.线程切换带来的原子性问题 count += 1 这一句高级语言的语句,往往需要多条CPU执令.可以分为3步: 将count值加载到寄存器 在寄存器中对count进行+1操作 将count值写回内存 所以,我们需要在高级语言的层面上,确保一些操作是原子性操作. 三.…
第一眼看到AbstractQueuedSynchronizer,通常都会有这几个问题. AbstractQueuedSynchronizer为什么要搞这么一个类? 这个类是干什么的.有什么用? 这个类的实现原理是什么? 下面我边学边教,来解答这3个问题. 问题一:AbstractQueuedSynchronizer产生的背景 AbstractQueuedSynchronizer 我这里用简写AQS表示.如果开发者想自己定义一个同步器怎么写?Java程序员用C++写个同步器不现实,这时如果有一个用…
一.线程池的介绍 线程池一种性能优化的重要手段.优化点在于创建线程和销毁线程会带来资源和时间上的消耗,而且线程池可以对线程进行管理,则可以减少这种损耗. 使用线程池的好处如下: 降低资源的消耗 提高响应的速度 提高线程的可管理性 二.线程池的使用 public class ThreadPoolExecutorDemo { static class Worker implements Runnable{ @Override public void run() { try { Thread.slee…
一.CountDownLatch 文档描述 A synchronization aid that allows one or more threads to wait until* a set of operations being performed in other threads completes. 是一个同步帮助工具,允许一个或多个线程等待一系列其他线程操作完后,再执行. count down 倒计时 latch 插锁 在Java中Latch结尾的也叫 闭锁 简单示例 public c…
一.概念 利用锁机制实现线程同步,synchronized关键字的底层交由了JVM通过C++来实现 Java中的锁有两大特性: 互斥性 同一时间,只允许一个线程持有某个对象锁. 可见性 锁释放前,线程对变量的修改,后面获得锁的线程可见. 二.用法 synchronized修饰位置与锁的关系: 同步方法 -- 对象锁,当前实例对象 静态同步方法 -- 类对象锁,当前对象的Class对象 同步方法块 -- 对象锁,synchonized括号里配置的对象 public class Synchroniz…
介绍 JDK1.8引入CompletableFuture类. 使用方法 public class CompletableFutureTest { private static ExecutorService threadPool = new ThreadPoolExecutor(40, 100, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(20)); public String B() { System.out.println(&qu…
ThreadLocal,叫做线程本地存储,也可以叫做线程本地变量.ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量. 一.如何使用 class Accessor implements Runnable { private final int id; public Accessor(int id) { this.id = id; } @Override public void run() { while (!Thread.currentThread(…
参考文档 LinkedBlockingQueue和ArrayBlockingQueue的异同…