文章目录
回顾:
ThreadLocal缺点:
1.不可继承性(不能实现父子线程间的数据传递)
2.脏数据---->ThreadLocal +线程池(复用)线程的复用会复用线程相关的静态变量
3.内存溢出
单例模式:
1.饿汉方式(线程安全的)
2.懒汉方式(按需初始化)
自定义阻塞队列:
生产者在队列满的时候就会休眠(sleep/wait /Locksupport)
消费者在队列为空时进行休眠
乐观锁
它认为一般情况不会发生并发冲突,所以只有在进行数据更新的时候,才会检测并发冲突,如果没有冲突执行修改,如果有冲突则返回失败。
CAS(乐观锁的一种实现),ABA,JUC
乐观锁的缺点:
总是需要去竞争锁,进而导致发生线程切换,挂起其他线程;所以性能不高。
CAS:(Compare and swap 比较并且交换)
V(内存值)A(旧值) B(新值)
V==A 如果为true(没有并发冲突)------> V就修改成B
如果为false(并发冲突)
一个CAS操作:
我们假设内存中的原数据V,旧的预期值A,需要修改的新值B。
- 比较 A 与 V 是否相等。(比较)
- 如果比较相等,将 B 写入 V。(交换)
- 返回操作是否成功。
CAS底层实现原理?
Java层面CAS 的实现是UnSafe类,是C++实现的方法。调用了C++的本地方法,通过调用操作系统的Atomic::cmpxchg(原子指令)来实现CAS操作。
- java 层面 CAS 利用的的是 unsafe 这个类提供的 CAS 操作;
- unsafe 的 CAS 依赖了的是 jvm 针对不同的操作系统实现的 Atomic::cmpxchg;
- Atomic::cmpxchg 的实现使用了汇编的 CAS 操作,并使用 cpu 硬件提供的 lock 机制保证其原子性。
CAS缺点:
ABA问题–>AtomicInteger是存在ABA问题。A:预期旧值 B:新值
ABA 的问题,就是一个值从A变成了B又变成了A,而这个期间我们不清楚这个过程。
ABA统一解决方案:增加版本号,每次修改之后更新版本号。
import java.util.concurrent.atomic.AtomicStampedReference;
/**
*ABA问题解决方案
*/
public class ThreadMain94 {
private static AtomicStampedReference money=
new AtomicStampedReference(100,1);
public static void main(String[] args) throws InterruptedException {
//转账线程1(-100)
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
boolean result= money.compareAndSet(100,
0,1,