并发包下类总结

synchronized 是在jvm底层的实现的锁, 互斥排他锁
可以锁定对象
实例方法,必须锁定同一个实例
静态方法,相当于锁定类,可以传入不同实例

  1. wait()
    调用wait()之前需要拿到当前对象的监视器(也是锁),执行后释放对象的监视器
    notify()
    调用notify()之前也需要拿到对象的监视器

  2. java内存模型
    Java内存模型定义了程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出这样的底层细节。
    此处变量包括实例字段,静态字段和构成数组对象的元素,但不包括局部变量和方法参数,因为这些是线程私有,不存在竞争。

  3. java各个线程是怎么彼此看到对方的变量?
    Java中定义了主内存和工作内存,所有变量都存储在主内存,每条线程还有自己的工作内存,保存了被该线程使用的变量的主内存副本拷贝。
    线程对变量的操作都在工作内存中操作(读取,赋值)不能直接读写主内存的变量。不同线程之间也无法直接访问对方工作内存的变量,线程间变量值的传递通过主内存。

  4. volatile特点,为什么能保证变量对所有线程的可见性。
    volatile是关键字,是java虚拟机提供的最轻量级的同步机制。

  1. 保证此变量的线程间可见性
  2. 禁止指令重排序优化
    Java内存模型定义了8中内存操作:
    lock和unlock
    把一个变量标识为一条线程独占的状态
    把一个处于锁定状态的变量释放出来,释放后的变量才能被其他线程锁定
    read和write
    把一个变量值从主内存传输到线程的工作内存,以便load
    把store操作从工作内存得到的变量的值,放入主内存的变量中
    Load和store
    把read操作从主内存得到的变量值放入工作内存的变量副本中。
    把工作内存的变量值传送到主内存,以便write
    Use和assgin
    把工作内存变量值传递给执行引擎
    把执行引擎值传递给工作内存变量值

Volatile的实现基于这8中内存间操作,保证一个线程对某个volatile变量的修改,一定会被另一个线程看见。

  1. ThreadLocal使用需要注意什么
    需要注意remove
    ThreadLocal的实现是基于一个ThreadLocalMap,在ThreadLocalMap中key是一个弱引用。
    通常弱引用都会和引用队列配合清理机制使用,但是ThreadLocal没这么做。
    废弃项目的回收依赖于显式地触发,否则就要等待线程结束,进而回收响应ThreadLocalMap,这就是很多OOM的来源,所以通常都会建议,应用自己来remove不要和线程池配合,因为worker线程一般不会退出。

原子性:
指令重排
可见性:

  1. 无锁
    CAS(V,E,N) V要更新的变量, E表示预期值, N表示新值
    CAS是由一条cpu指令完成的,所以保证安全

  2. AtomicInteger 内部定义了volatile int value,使用Unsafe通过偏移量valueOffset来赋值

  3. AtomicReference

  4. AtomicStampedReference 防止ABA问题,有一个int类型的stamp,内部封装了Pair

  5. AtomicIntegerArray

  6. AtomicIntegerFieldUpdater 基于反射可以使普通的类(如Person的id)的int属性变为原,通过newUpdater(修饰的class,修饰字段)来实现,Person的id必须为基本类型,用volatile修饰,必须为可变的实例变量,为public的,调用compareAndSet(person,expectId,newId)

  7. Vector 方法用synchronized 修饰,默认翻倍扩容,可以指定扩容的数量
    LockFreeVector 里面内部实现的是AtomicReferenceArray<AtomicReferenceArray>

  8. ReentrantLock
    在lock()后,一定要释放finally中unlock()
    是否锁定线程判断—lock.isHeldByCurrentThread()
    可重入 lock.tryLock()
    可中断 lock.lockInterruptibly() 可以相应中断
    可限时 lock.tryLock(5,TimeUnit.SECONDS)
    公平锁 new ReentrantLock(true) 先来先到的锁

内部实现:CAS状态,等待队列,park()

  1. Conditon 与ReentrantLock结合使用
    await() signal()

  2. Semaphore 共享锁,可以有多个许可,允许多个线程进入临界区,许可为1就相当于锁
    没有许可后需要等待
    acquire() release()
    tryAcquire()
    acquire(int)一个线程申请多个许可
    release(int)申请多个线程同样释放多个线程

  3. ReadWriteLock ReentrantReadWriteLock
    在没有write线程时,所有read是无等待线程,
    读读不互斥
    读写互斥
    写写互斥

  4. CountDownLatch 倒数计数器 到达一个时间线
    new CountDownLatch(10)
    end.countDown()
    end.await()

  5. CyclicBarrier 循环栅栏 到达一个时间线
    计数器可以反复使用,多个线程相互等待,可做循环复用。
    new CyclicBarrie(n,runnable)
    例:士兵集合,任务完成,
    await()

  6. LockSupport
    LockSupport.park() 线程挂起
    LockSupport.unpark(Thread)
    unpark()可以在park()后执行,不容易引起线程终结

  7. AQS -----AbstractQueuedSynchronizer
    FIFO结构

维护了一个volatile int state(代表同步状态)和一个FIFO(CLH)线程等待队列(多线程争夺资源时进入队列),提供了两种同步方式,独占(Exclusive)模式和共享(Shared)模式
1) AQS通过Node内部类构造的一个双向链表结构的同步队列,来完成线程获取锁的排队工作,当有线程获取锁失败后就添加到队尾。
2) Node类是对要访问同步代码的线程的封装,包含线程本身和状态(waitStatus):5种值分别表示是否被阻塞,是否等待唤醒,是否已经被取消等。每个Node节点关联其pre节点和next节点,方便线程释放锁后快速唤醒下一个在等待的线程,是一个FIFO过程。
3) 通过内部类ConditionObject构建等待队列(可有多个),当Condition调用wait()方法后,线程将加入等待队列中,而当Condition调用signal()方法后,线程将从等待队列移动到同步队列中进行锁竞争。
4) AQS和Condition各自维护了不同的队列,在使用Lock和Condition时就是两个队列的相互移动。
定义了两种资源共享方式:共享和独占

二:自定资源共享方式
主要实现以下方法:

isHeldExclusively(): 该线程是否正在独占资源。用到condition时才需要实现
tryAcquire(int):独占方式,尝试获取资源
tryRelease(int):独占方式,尝试释放资源
tryAcquireShare(int):共享方式
tryReleaseShare(int):共享方式

三: acquire—release
acquire是一种以独占方式获取资源,如果获取到资源,线程直接返回,否则进入等待队列,直到获取到资源为止,整个过程忽略中断影响

在AQS中维护了一个FIFO的同步队列,当线程获取同步状态失败后,会加入到这个CLH同步队列的队尾并一直保持自旋。在CLH同步队列中的线程在自旋时会判断其前驱节点是否为首节点,如果是首节点则不断尝试获取同步状态,获取成功则退出CLH同步队列。当线程执行完逻辑后,会释放同步状态,释放后会唤醒其后继节点。

内部调用了LockSupport来控制线程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值