多线程系列

多线程之原子性

2020-01-24  本文已影响0人  小蜗牛Aaron

原子操作

原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,也不可以被切割而只执行其中的一部分(不可中断性)。
将整个操作视作一个整体,资源在该次操作中保持一致,这是原子性的核心特征。

竞态条件以及临界区

竞态条件:当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。
临界区,就是导致静态条件发生的代码区。

CAS机制

CAS 属于硬件同步原语,处理器提供的内存操作指令,保证原子性。
CAS 操作需要两个参数,一个旧值和一个目标值,修改前先比较旧值是否改变,如果没变,将新值
赋给变量,否则不做改变。
JAVA中的sun.misc.Unsafe类提供了CAS机制。

原子类

AtomicBoolean:原子更新布尔类型
AtomicInteger:原子更新整型
AtomicLong:原子更新长整型
AtomicIntegerArray:原子更新整型数组里的元素。
AtomicLongArray:原子更新长整型数组里的元素。
AtomicReferenceArray:原子更新引用类型数组里的元素。
AtomicReference:原子更新引用类型。
AtomicStampedReference:原子更新带有版本号的引用类型
AtomicMarkableReference:原子更新带有标记位的引用类型。
计数器: DoubleAdder、 LongAdder
计数器增强版,高并发下性能更好
DoubleAccumulator、 LongAccumulator
是计数器的增强版,可自定义累加规则

CAS 存在的问题

  1. 仅针对单个变量的操作,不能用于多个变量来实现原子操作。
  2. 循环+CAS,自旋的实现让所有线程都处于高频运行,争抢CPU执行时间的状态 。如果操作长时间不成功,会带来很大的CPU资源消耗。
  3. ABA问题。(无法体现出数据的变动)。

cas应用场景

ABA问题

image.png

线程组

ThreadGroup的提出是为了方便线程的管理,通过它可以批量设定一组线程的属性,比如setDaemon,设置未处理异常的处理方法,设置统一的安全策略等等;也可以通过线程组方便的获得线程的一些信息,尽量不要使用,会带来线程安全问题

启动线程

启动线程的方式只有一种:new Thread().start()

终止线程

image.png

理想输出:i=0 j=0
程序执行结果:i=1 j=0
没有保证同步代码块里面数据的一致性,破坏了线程安全

interrupt

1.interrupt方法并不会中断线程,知识打上中断标记
2 . 如 果 目 标 线 程 在 调 用 wait() 、 wait(long) 方 法 、 join() 、 join(long, int) 、join(long, int)、sleep(long, int)或sleep(long, int)等方法后,处于WAITING、Timed Waiting状态时,该线程被调用interrupt方法后,线程的WAITING、Timed Waiting状态将被清除,并抛出InterruptedException异常。

  1. park()\parkNanos方法执行后,线程也处于 WAITING、Timed Waiting,也会被唤醒,但是不会抛异常,且有很诡异的情况发生。

4、如果目标线程是被I/O 或者NIO中的Channel所阻塞,同样,I/O操作会被中断或者返回特殊异常值。达到终止线程的目的。
5、如果以上条件都不满足,则会设置此线程的中断状态

Deamon 守护线程

是指在程序运行的时候在后台提供一种通用服务的线程,进程结束时,会杀死所有守护线程。
(1)thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个
IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。
(2)在Daemon线程中产生的新线程也是Daemon的。
(3)守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至
在一个操作的中间发生中断。

CountDownLatch

image.png

Semaphore

Semaphore是一个计数信号量,常用于限制可以访问某些资源(物理或逻辑的)线程数目。
简单说,是一种用来控制并发量的共享锁。

image.png

CyclicBarrier

循环栅栏,可以循环利用的屏障。
举例:排队上摩天轮时,每到齐四个人,就可以上同一个车厢。


image.png
上一篇 下一篇

猜你喜欢

热点阅读