首页
关于
友链
Search
1
wlop 4K 壁纸 4k8k 动态 壁纸
1,470 阅读
2
Nacos持久化MySQL问题-解决方案
932 阅读
3
Docker搭建Typecho博客
752 阅读
4
滑动时间窗口算法
728 阅读
5
Nginx反向代理微服务配置
699 阅读
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
登录
Search
标签搜索
java
javase
docker
java8
springboot
thread
spring
分布式
mysql
锁
linux
redis
源码
typecho
centos
git
map
RabbitMQ
lambda
stream
少年
累计撰写
189
篇文章
累计收到
24
条评论
首页
栏目
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
页面
关于
友链
搜索到
2
篇与
的结果
2022-04-21
可见性和有序性
可见性可见性:一个线程对主内存的修改可以及时的被其它线程观察到。导致共享变量在线程间不可见的原因:线程交叉执行重排序结合线程交叉执行共享变量更新后的值没有在工作内存与主存间及时更新可见性-synchronizedJMM关于synchronized的两条规定:线程解锁前,必须把共享变量的最新值刷新到主内存线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值(注意,加锁与解锁是同一把锁)可见性-volatilevolatile,通过加入内存屏障和禁止重排序优化来实现。对volatile变量写操作时,会在写操作后加入一条store屏障指令,将本地内存中的共享变量值刷新到主内存对volatile变量读操作时,会在读操作前加入一条load屏障指令,从主内存中读取共享变量volatile写:volatile读:有序性Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性.可通过volatile、synchronized、Lock保证有序性。有序性-happens-before原则程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作锁定规则:一个unLock操作先行发生于后面对同一个锁的lock操作volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C线程启动规则:Thread对象的start()方法先行发生于此线程的每一个动作线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始线程安全性-总结原子性:Atomic包、CAS算法、synchronized、Lock可见性:synchronized、volatile有序性:happens-before
2022年04月21日
178 阅读
0 评论
2 点赞
2022-04-20
原子性-Atomic类常见的使用
1、(信号量)Semaphore+(闭锁)CountDownLatch+(常用源自类)AtomicIntegerpackage com.yanxizhu.demo.concurrency.atomic; import com.yanxizhu.demo.concurrency.annotation.ThreadSafety; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicInteger; /** * @description: 线程安全 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/19 20:05 * @version: 1.0 */ @Slf4j @ThreadSafety public class DemoSemaphoreAndCountDownLatchAndAtomic { //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; //累加总和 private static AtomicInteger count = new AtomicInteger(0); public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(clientsTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(concurrencyTotal); for (int i = 0; i < clientsTotal; i++) { executorService.execute(()->{ try { semaphore.acquire(); add(); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("累加结果为count=【{}】",count.get()); } /** * 累加 */ private static void add(){ //说明:incrementAndGet、getAndIncrement类似,i++与++i count.incrementAndGet(); count.getAndIncrement(); } }运行结果:累加结果为count=【10000】2、AtomicReferencepackage com.yanxizhu.demo.concurrency.atomic; import com.yanxizhu.demo.concurrency.annotation.ThreadSafety; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.atomic.AtomicReference; /** * @description: AtomicReference * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/20 21:09 * @version: 1.0 */ @Slf4j @ThreadSafety public class DemoAtomicReference { public static AtomicReference<Integer> count = new AtomicReference<>(0); public static void main(String[] args) { count.compareAndSet(0, 2); count.compareAndSet(0, 1); count.compareAndSet(1, 3); count.compareAndSet(2, 4); count.compareAndSet(3, 5); log.info("count结果为【{}】",count.get()); } }运行结果:count结果为【4】3、AtomicIntegerFieldUpdaterpackage com.yanxizhu.demo.concurrency.atomic; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; /** * @description: AtomicIntegerFieldUpdater,原子性修改 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/20 21:17 * @version: 1.0 */ @Slf4j public class DemoAtomicIntegerFieldUpdater { private static AtomicIntegerFieldUpdater<DemoAtomicIntegerFieldUpdater> updater = AtomicIntegerFieldUpdater.newUpdater(DemoAtomicIntegerFieldUpdater.class, "count"); @Getter public volatile int count = 100; private static DemoAtomicIntegerFieldUpdater demoAtomicIntegerFieldUpdater = new DemoAtomicIntegerFieldUpdater(); public static void main(String[] args) { if(updater.compareAndSet(demoAtomicIntegerFieldUpdater, 100, 200)) { log.info("updater succcess1,{}", demoAtomicIntegerFieldUpdater.getCount()); } if(updater.compareAndSet(demoAtomicIntegerFieldUpdater, 100, 200)) { log.info("updater succcess2,{}", demoAtomicIntegerFieldUpdater.getCount()); }else { log.info("updater fail,{}", demoAtomicIntegerFieldUpdater.getCount()); } } }运行结果:updater succcess1,200 updater fail,2004、AtomicStampedReference主要用于解决CAS中ABA问题,主要是AtomicStampedReference类中compareAndSet方法多了一个stamp的比较。stamp是每次更新来维护的。 public boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) { Pair<V> current = pair; return expectedReference == current.reference && expectedStamp == current.stamp && ((newReference == current.reference && newStamp == current.stamp) || casPair(current, Pair.of(newReference, newStamp))); } 5、LongAdderJDK1.8后新增了LongAdder。AtomicLong:是基于 CAS 方式自旋更新的;LongAdder: 是把 value 分成若干cell,并发量低的时候,直接 CAS 更新值,成功即结束。并发量高的情况,CAS更新某个cell值和需要时对cell数据扩容,成功结束;更新失败自旋 CAS 更新 cell值。取值的时候,调用 sum() 方法进行每个cell累加。AtomicLong: 包含有原子性的读、写结合的api;LongAdder :没有原子性的读、写结合的api,能保证结果最终一致性。低并发:低并发场景AtomicLong 和 LongAdder 性能相似。高并发:高并发场景 LongAdder 性能优于 AtomicLong。6、AtomicLongArray主要用于原子修改数组 // 下标, 期望值 更新值 public final boolean compareAndSet(int i, long expectedValue, long newValue) { return AA.compareAndSet(array, i, expectedValue, newValue); }通过传入下标、期望值、要更新的值进行修改。7、AtomicBoolean public final boolean compareAndSet(boolean expectedValue, boolean newValue) { return VALUE.compareAndSet(this, (expectedValue ? 1 : 0), (newValue ? 1 : 0)); }package com.yanxizhu.demo.concurrency.atomic; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicBoolean; /** * @description: 结果,最后只会执行一次 * @author: <a href="mailto:batis@foxmail.com">清风</a> * @date: 2022/4/20 22:05 * @version: 1.0 */ @Slf4j public class DemoAtomicBoolean { private static AtomicBoolean isHappen = new AtomicBoolean(false); //用户数量 private static final int clientsTotal = 5000; //并发数量 private static final int concurrencyTotal = 200; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newCachedThreadPool(); //信号量 final Semaphore semaphore = new Semaphore(clientsTotal); //闭锁 final CountDownLatch countDownLatch = new CountDownLatch(concurrencyTotal); for (int i = 0; i < clientsTotal; i++) { executorService.execute(()->{ try { semaphore.acquire(); test(); semaphore.release(); } catch (InterruptedException e) { log.error("出现错误:【{}】", e.getMessage()); } countDownLatch.countDown(); }); } countDownLatch.await(); executorService.shutdown(); log.info("isHappen结果为count=【{}】",isHappen.get()); } public static void test() { //从false变成true是一次原子操作,只会执行一次 if(isHappen.compareAndSet(false, true)) { log.info("execute .. {}", isHappen); } } }运行结果:execute .. true isHappen结果为count=【true】
2022年04月20日
172 阅读
0 评论
2 点赞