线程-相关知识点

耐心是一切聪明才智的基础。

java内存模型

java内存模型(java memory model)是一种规范,是解决多线程在用共享内存时,因为3级缓存,编译器重排,cpu乱序执行,导致的线程安全问题。
3种问题:原子性,可见性,有序性

关键字volatile

保证可见性,有序性
在实现双重检测单例时,就是因为利用了有序性,保证创建对象时按照分配内存->内存中创建对象-> 变量指向内存的执行顺序。
不能保证原子性,导致一些依赖原值的修改操作,在多线程中会出现问题。
可以用AtomicInteger->longAdder(分段cas并发时性能好)来实现线程安全。(基于CAS)
写操作前插入写写、写操作后添加写读、读操作前添加读读、读操作后添加读写内存屏障,保证可见性和有序性。

实现线程安全思路
  • 锁(s锁,AQS锁
  • cas(AtomicInteger
  • 一个线程一套(ThreadLocal
S锁

jdk1.5实现,是个笨锁,操作有用户态内核的上下文切换。
jdk1.6升级了,根据竞争程度一级一级升级。这里也涉及到了自旋锁,因为自旋锁在竞争比较激烈比较费cpu,所以最后转为笨锁,一了百了。


image.png
CAS算法

内存值,旧值,新值
线程旧值新值运算完之后,回写内存值时,对比内存值旧值是否相等。
ABA问题可以加版本号处理。
争抢比较多比较费cpu,但是比起s锁没有上下文切换开销。

AQS抽象同步队列

state为0说明没有正在运行的线程,可以直接运行,运行会把state改为1,这时候如果还是这个线程重入加锁,会再进行累加。
双向链表(CHL),有正在运行的线程,又不是自己,r锁默认是非公平锁,会先加到尾插到链表里。
r锁默认是非公平锁,可以创建的时候指定,非公平锁时新加锁的线程会先cas2次去争抢锁,抢到就继续执行,否则park放到链表尾部。公平锁模式,会直接放到park链表尾部。非公平锁具有更高的吞度量,因为新加入线程可能直接执行,没有暂停,放入队列,再唤醒的开销。

Locksupport.park

  • 响应中断,但不抛出异常。
  • 底层permit布尔值,控制挂起执行。

封装的一些类:

  • ReentrantLock
    比起s锁,公平锁,可中断,有状态。
    代码块,需要手动释放。
    • lock.Condition实现了s锁的wait nofity机制。
      对应await,signal方法。
  • ReentrantReadWriteLock 读写锁。
  • Semaphore 信号量,控制线程的数量。
    • acquire()数量加一,满了阻塞。
    • release()数量减一。
  • CountDownLatch 倒计时 实现线程同时运行。
    • await()阻塞,等待数减到0。
    • countdown()数量减一。
  • CyclicBarrier 循环屏障(比起countdownLatch可以复用reset)
    • await()阻塞,当所有数量线程都走到此步,继续执行。
ThreadLocal

https://www.jianshu.com/p/a20af7b7d113

image.png

你可能感兴趣的:(线程-相关知识点)