锁与volatile的内存语义 1.锁的内存语义 2.volatile内存语义 3.synchronized内存语义 4.Lock与synchronized的区别 5.ReentrantLock源码实例分析 1.锁的内存语义 锁是java并发编程中最重要的同步机制.锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息. 1.1 锁释放和获取的内存语义 当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中: 当线程获取锁时,JMM会当前线程拥有的本地内存共…
如果你使用过杀毒软件,可能会发现全盘杀毒太耗时间了,这时你如果点击取消杀毒按钮,那么此时你正在中断一个运行的线程. java为我们提供了一种调用interrupt()方法来请求终止线程的方法,下面我们就一起来学习一下线程的中断. 每一个线程都有一个boolean类型标志,用来表明当前线程是否请求中断,当一个线程调用interrupt() 方法时,线程的中断标志将被设置为true. 我们可以通过调用Thread.currentThread().isInterrupted()或者Thread.int…
CAS(Compare And Swap)导致的ABA问题 问题描述 多线程情况下,每个线程使用CAS操作欲将数据A修改成B,当然我们只希望只有一个线程能够正确的修改数据,并且只修改一次.当并发的时候,其中一个线程已经将A成功的改成了B,但是在线程并发调度过程中尚未被调度,在这个期间,另外一个线程(不在并发中的请求线程)将B又修改成了A,那么原来并发中的线程又可以通过CAS操作将A改成B 测试用例: public class AbaPro { private static final Rando…
一.概念理解 首先我们先来了解一下什么是重排序:重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段. 从Java源代码到最终实际执行的指令序列,会分别经历下面3种重排序,如下图所示 上述的1属于编译器重排序,2和3属于处理器重排序.这些重排序可能会导致多线程程序出现内存可见性问题.在单线程程序中,对存在控制依赖的操作重排序,不会改变执行结果(这也是as-if-serial语义允许对存在控制依赖的操作做重排序的原因):但在多线程程序中,对存在控制依赖的操作重排序,可能会改变…
传统的原子锁AtomicLong/AtomicInt虽然也可以处理大量并发情况下的计数器,但是由于使用了自旋等待,当存在大量竞争时,会存在大量自旋等待,而导致CPU浪费,而有效计算很少,降低了计算效率. 而LongAdder是根据ConcurrentHashMap这类为并发设计的类的基本原理——锁分段,通过维护一个计数数组cells来保存多个计数副本,每个线程只对自己的副本进行操作,最后汇总来得到最终结果. Adder的英文意思为加法器,从字面意思上就可以理解,LongAdder的作用是用来进行…
背景   “线下没问题的”. “代码不可能有问题 是系统原因”.“能在线上远程debug么”    线上问题不同于开发期间的bug,与运行时环境.压力.并发情况.具体的业务相关.对于线上的问题利用线上环境可用的工具,收集必要信息 对定位问题十分重要.    对于导致问题的bug.资源瓶颈很难直观取得数据,需要根据资源使用数据.日志等信息推测问题根源.并且疑难问题的定位通常需要使用不同的方法追根溯源.    这篇wiki我对自己使用过的工具做了整理,并分享一些案例. 1.  常见问题1.1 可用性…
一.final域的重排序规则 对于final域,编译器和处理器要遵循两个重拍序规则: 1.在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序. 2.初次读一个包含final域的对象的应用,与随后初次读这个final域,这两个操作之间不能重排序 下面通过一个示例来分别说明这两个规则: public class FinalTest { int i;//普通变量 final int j; static FinalTest obj; publi…
一.继承Thread类 public class Demo1 extends Thread { public Demo1(String name) { super(name); } @Override public void run() { while(!interrupted()) { System.out.println(getName() + "线程执行了 .. "); try { Thread.sleep(200); } catch (InterruptedException…
1.什么是ThreadLocal ThreadLocal顾名思义是线程局部变量.这种变量和普通的变量不同,这种变量在每个线程中通过get和set方法访问, 每个线程有自己独立的变量副本.线程局部变量不存在多个线程同时对同一个变量的操作,所以不会有线程安全问题. 2.ThreadLocal变量的使用 public class ThreadLocalDemo { private ThreadLocal<Integer> threadLocal = new ThreadLocal<Intege…
单例模式我想这个设计模式大家都很熟悉,如果不熟悉的可以看我写的设计模式系列然后再来看本文.单例模式通常可以分为:饿汉式和懒汉式,那么分别和线程安全是否有关呢? 一.饿汉式 先看代码: package com.roocon.thread.t5; public class Singleton { private Singleton(){ } private static Singleton instance = new Singleton(); public static Singleton get…