并发特性及并发常用工具

了解并发工具之前咱们先了解下并发编程的三个特性。这里只讲原理,有想了解底层的小伙伴idea安装bytecode查看字节码,需要具备CPU和汇编相关知识,咱们这里就不叙述了。

并发编程的三个特性

可见性

一个线程修改了值,另一个线程不能看到(线程本地缓存)
JVM_内存管理 篇有这方面的知识,想了解的可以点击查看,有可能会帮到您

缓存一致性协议了解一哈
   两个CPU同时读取缓存行的数据,读写时会触发缓存一致性
   MESI Cache一致性(MSI...)
       M:Modified 当前缓存行数据已被修改,其他CPU为Invalid
       E:Exclusive 独享,其他CPU不存在这个数据
       S:Shared 共享的
       I:Invalid 无效的,需要去主存重新加载
缓存行再了解一哈
    内存读取是按块读取,又称缓存行,默认大小为64byte
    @Contended:自动补充缓存空间,让变量在一个缓存行
      -XX:-RestrictContended=默认是关闭的,需要声明开启;只有1.8以上支持

有序性

程序执行的顺序按照代码的先后顺序执行

乱序:不影响单线程的最终一致性
构造方法不要进行线程启动,会造成指令重排(init和i_load)造成this逸出

原子性

要么都成功,要么都失败,中间过程不受上下文切换影响

Synchronized

基础用法

synchronized的锁是对象不是代码
synchronized即保证了原子性又保证了可见性
Synchronized是可重入锁,即同一个线程两个同步方法是可以调用的
Synchronized遇到未捕捉的异常会释放锁
Synchronized是非公平锁
锁的升级过程:
		找到对应的锁对象,markwork记录这个线程ID(偏向锁)--》
		如果有线程线程争用,升级为自旋锁(10)
		如果还申请不到锁,升级为重量级锁-OS(释放线程)
注意:
    非静态Synchronized的方法锁对象默认是当前类的对象
    静态Synchronized的方法默认是当前类的Class对象
选择方式:
	如果锁执行时间短,线程比较少,使用自旋锁
	如果锁时间长,线程比较多用OS锁

volatile

作用:
	1、保证线程可见性
	2、禁止指令重排序
volatile的实现细节
	字节码层面
		ACC_VOLATILE
	JVM层面
		volatile内存区的读写都加屏障
		读屏障:LoadLoad --->volatile--->LoadStore
		写屏障:StoreStore--->volatile--->StoreLoad
	OS和硬件层面
		hsdis - HotSpot Dis Assembler
		windows下使用 lock指令实现

自增线程安全三种方式

Atomicxxx
		CAS自旋
LongAdder
		分段锁,适合高并发场景
synchronized

线程安全工具

ReentrantLock

同步,可重入锁

lock = new ReentrantLock();//如果参数加上true就是公平锁,不是绝对的公平
lock.lock();//获取锁
lock.unlock();//解锁
lock.lockInterruptibly();//线程可以被打断

CountDownLatch

向下渐少,直到为0才能进行下面的操作

CountDownLatch latch = new CountDownLatch(100);
latch.countDown(); //线下减1
latch.await();//等待所有线程执行完毕
latch.getCount() //查看还有多少线程执行,可以查看进度

CyclicBarrier

栅栏 满多少线程执行动作

CyclicBarrier cb = new CyclicBarrier(20, () -> System.out.println("-------"));
for(int i=0;i<100;i++) {
  new Thread(()->{
    cb.await(); //等待上面的线程满执行
  }).start();
}

ReadWriteLock

读写锁

ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
Lock readLock = readWriteLock.readLock();//共享读锁
Lock writeLock = readWriteLock.writeLock();//排它写锁
​``````properties

Semaphore

信号量,允许同一时间最大的线程工作个数,用于限流

Semaphore semaphore = new Semaphore(3);
semaphore.acquire(1);//获得许可
semaphore.release();//释放许可
Exchanger

交换器:两个线程之前的值进行交换

Exchanger<String> exchanger = new Exchanger<>();
new Thread(()->{
	String s = "T1";
	try {
		s = exchanger.exchange(s);
	} catch (Exception e) {
		//
	}
	System.out.println(Thread.currentThread().getName() + " " + s);
},"t1").start();

new Thread(()->{
	String s = "T2";
	try {
		s = exchanger.exchange(s);
	} catch (Exception e) {
		//
	}
	System.out.println(Thread.currentThread().getName() + " " + s);
},"t2").start();
LockSupport

线程在任意位置阻塞

线程工具类
park //阻塞
unpark //解锁
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值