【并发编程】并发编程的三大特性

目录

1、原子性

1.1 原子性的定义

1.2 volatile count++流程分析

1.3如何保证原子性

1.3.1 synchronized

1.3.2 CAS

​编辑

1.3.3 lock锁

1.3.4 ThreadLocal

ThreadLocal实现原理:

ThreadLocal内存泄漏问题:

2、可见性

2.1 可见性定义

2.2 解决可见性的方式

2.2.1 volatile

2.2.2 synchronized

2.2.3 Lock

2.2.4 final

3、有序性

3.1 有序性定义

3.2 解决有序性

3.2.1 as-if-serial

3.2.2 happens-before

3.2.3 volatile


1、原子性

1.1 原子性的定义

        原子性指一个操作是不可分割的,不可中断的,一个线程在执行时,另一个线程不会影响到他。

原子性:一个操作是不可分割的,要么一起成功,要么一起失败

1.2 volatile count++流程分析

  • 从主内存获取数据到寄存器
  • 在CPU内部执行+1 操作
  • 将CPU寄存器数据写回到主内存

1.3如何保证原子性

1.3.1 synchronized

synchronized 可以避免让多线程同时操作临界资源,同一时间点,只会让一个线程去操作临界资源,

原理:

  • 当线程操作资源时,先要获取锁资源(monitorenter),获取到锁资源后,才能进行后面的资源操作
  • 当指令执行完毕,锁资源会释放(monitorexit),其他线程可以进行锁资源的获取

示例:

public class Atomicity {
    public static int count;

    public static void increment() {
        synchronized (Atomicity.class) {
            count++;
        }
    }

}

对代码进行编译查看

javac -encoding utf-8  .\Atomicity.java
javap -v .\Atomicity.class

1.3.2 CAS

cas: compare and swap也就是比较和交换,他是一条CPU的并发原语。

CAS 多线程操作临界资源

public class Atomicity {
    private static AtomicInteger count = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                count.incrementAndGet();
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                count.incrementAndGet();
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(count);
    }

}

//200

CAS操作资源能够保证原子性,主要是他在替换内存的某个位置的值时,首先查看内存中的值与预期值是否一致,如果一致,执行替换操作。这个操作是一个原子性操作。

查看AtomicInteger源码

private static final Unsafe U = Unsafe.getUnsafe();
private static final long VALUE
        = U.objectFieldOffset(AtomicInteger.class, "value");

private volatile int value;
incrementAndGet 借助了Unsafe类的 getAndAddInt()方法,可以看到,最终指向了一个native方法
 public final int getAndAddInt(Object o, long offset, int delta) {
        int v;
        do {
            v = getIntVolatile(o, offset);
        } while (!weakCompareAndSetInt(o, offset, v, v + delta));
        return v;
 }

public native int     getIntVolatile(Object o, long offset);

getIntVolatile 方法又两个参数,该方法的主要作用是:获取当前对象var1在该对象指定偏移量var2上的值

  • var1:待计算的对象
  • var2:在对象上的偏移量

        除了这个方法,像Unsafe中的getIntVolatile、getBooleanVolatile、getByteVolatile、getShortVolatile、getCharVolatile、getLongVolatile、getFloatVolatile、getDoubleVolatile等方法都是类似的作用。

CAS的缺点:CAS只能保证对一个变量的操作是原子性的,无法实现对多行代码实现原子性。

ABA问题:

  • 19
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lxtx-0510

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值