![](https://img-blog.csdnimg.cn/9ec6b6c3bf544f13b1950508cebf1730.jpeg?x-oss-process=image/resize,m_fixed,h_224,w_224)
并发编程
文章平均质量分 90
并发编程知识点小结
shark-chili
这个作者很懒,什么都没留下…
展开
-
java中的cow思想
前言日常开发时,我们使用使用ArrayList自然是线程不安全的,这个是众所周知的,因为常规下线程操作或者业务代码是不会涉及多线程操作单集合的高并发场景的。一旦在高并发对某个集合需要进行又读又写的情况时,还有人敢用ArrayList嘛?vector真的线程安全嘛?对于上述情况,可能很多人都会想到使用vector,确实,如下图所示,vector代码中cow思想,高并发线程安全的最佳解决方案工作原理与传统集合的比对...原创 2021-08-05 22:23:06 · 664 阅读 · 3 评论 -
Java并发编程进阶面试题专栏导航(周更)
这是笔者目前为止整理的并发编程,笔者后续会在每个周末进行周期性的补充和迭代,欢迎读者进行补充指正。,这里面会有笔者精心挑选的并发、JVM、MySQL数据库专栏,也有笔者日常分享的硬核技术小文。,同时我的公众号也有我精心整理的。原创 2024-01-07 16:20:19 · 1296 阅读 · 0 评论 -
CompletableFuture异步多任务最佳实践
Java并发编程实战》一书中,Brian Goetz和合著者们为线程池大小的优化提供了不少中肯的建议。这非常重要,如果线程池中线程的数量过多,最终它们会竞争稀缺的处理器和内存资源,浪费大量的时间在上下文切换上。反之,如果线程的数目过少,正如你的应用所面临的 情况,处理器的一些核可能就无法充分利用。原创 2023-12-10 12:37:38 · 3932 阅读 · 4 评论 -
简单聊聊FutureTask
FutureTask可看作对异步任务的封装,异步任务在它的封装下,可灵活进行阻塞获取结果或者中断。原创 2022-03-27 23:56:23 · 484 阅读 · 2 评论 -
Java并发编程基础总结
线程是比进程更小的单位,所以在进行线程切换时的开销会远远小于进程,所以线程也常常被称为轻量级进程。每一个进程中都会有一个或者多个线程,在JVM中每一个Java线程都会共享他们的进程的堆区和方法区。但是每一个进程都会有自己的程序计数器虚拟机栈和本地方法栈。Java天生就是一个多线程的程序,我们完全可以运行下面这段代码看看一段main方法中会有那些线程在运行// 获取 Java 线程管理 MXBean// 不需要获取同步的 monitor 和 synchronizer 信息,仅获取线程和线程堆栈信息。原创 2023-12-13 08:38:09 · 725 阅读 · 1 评论 -
深入理解Java关键字volatile
禁止指令重排序的话,1、2、3的顺序操作很可能变成1、3、2进而导致一个线程执行1、3创建一个未初始化却不为空的对象,而另一个线程判空操作判定不空直接返回出去,从而导致执行出现异常。但是CPUC先收到CPUB的通知先改为200再收到CPUA的通知变为100,这就导致的数据不一致的问题,即事务串行化失败。这时候CPU2再去内存从取变量i,进行+1,因为CPU1修改的值没有写回内存,所以CPU2操作的变量i最终结果是。是总线嗅探的改良版,他很好的解决了总线的带宽压力,以及很好的解决了数据一致性问题。原创 2023-12-13 08:37:44 · 863 阅读 · 1 评论 -
聊聊Java关键字synchronized
具体例子,某段线程得到锁Test.class之后,执行临界代码逻辑,可能会先执行变量b初始化的逻辑,在执行a变量初始化的逻辑,但是最终结果都会执行a+b的逻辑。每个线程使用synchronized获得锁操作临界资源时,首先需要获取临界资源的值,为了保证临界资源的值是最新的,JMM模型规定线程必须将本地工作内存清空,到共享内存中加载最新的进行操作。正是由于锁互斥的失败,导致两个线程同时到临界区域加载资源,获得的count都是0,经过自增后都是1,导致数据少了1。原创 2022-02-13 16:34:31 · 4230 阅读 · 0 评论 -
用版本迭代展示并发编程实践
需求分析有些业务数据可能需要经过sql查询以及复杂的运算,所以耗时可能很长,对于这样的数据我们常用缓存来解决问题,所以本文就会经过几个版本的迭代完成基于JUC工具打造一个相对高性能的缓存demo。我们不妨模拟这样一个业务场景,我们的数据是需要通过字符串id去数据库查询,然后经过复杂计算再返回。相同的id再经计算的结果都是一样的。例如:使用id为"666"查出来的结果永远都是666从最简单的缓存出发如下所示,需要缓存那么我们就需要一个数据结构进行缓存,第一个demo我们就用hashmap作为初始数据结原创 2022-02-10 23:12:09 · 394 阅读 · 0 评论 -
来聊聊AQS源码
在JUC并发包下,有可重入锁(ReentrantLock)、倒计时门闩(CountDownLatch)等并发流程工具,其底层对于线程资源争抢以及获取执行权都是基于AQS实现的。他的思想也很巧妙,将多线程比作一个个节点放到一个双向队列中,争抢到的节点可以修改一个为state的状态值,这个state我们这里暂且可以理解为争抢到资源的线程使用情况,只有当前获取执行权的线程将state设置到某个值的时候,其他线程CAS察觉到这个值,就开始抢夺执行权。原创 2022-02-08 22:30:21 · 403 阅读 · 0 评论 -
JUC常见并发流程工具总结
倒计时门闩,只有倒计时门闩值变为0时,阻塞状态才会结束。信号量常用于控制多线程争抢有些资源后才能工作的场景。例如我们给信号量设置资源总数为3,只有拿到3个资源的线程才能进行工作,其他线程必须等待使用使用资源的线程释放后才能进行争抢。当A线程需要等待某个条件的时候,它就去执行condition.await()方法,一旦执行了await()方法,线程就会进入阻塞状态。如果线程B执行condition.signal()方法,则JVM就会从被阻塞线程中找到等待该condition的线程。原创 2022-02-07 23:32:24 · 564 阅读 · 0 评论 -
Java并发容器总结
我们日常开发会经常用到各种容器类,容器类为我们提供了大量简化数据操作的API,提高了我们的数据处理的效率。虽然说容器类使用十分方便,但是在多线程情况下,容器类使用不当可能导致线程安全问题,所以Java设计者们为我们提供线程安全操作的并发容器类解决这些问题。但是使用并发容器就真的完全可以避免线程安全问题了吗?它们使用的几个注意事项不知道你是否了解过,这篇文章我们就会基于Map和List两个比较常用的容器类来展开问题的探讨。原创 2022-02-06 11:29:56 · 1687 阅读 · 0 评论 -
来聊聊final关键字
关键字可用于修饰类、方法、变量,通过修饰后可以使类不可被继承,方法不可被重写,变量不可被修改。正是因为这样使得关键字修饰的东西天生自带线程安全属性,而且也没有额外的开销。必须在声明时候就进行初始化,否则无法正常通过编译:final修饰局部变量正确的使用方式应该是如下所示,如果b没有赋值的话,编译期都过不了:当然若变量还有static修饰的话,还可以在静态代码块中被初始化若没有修饰,也可以在构造方法或者普通代码块中被初始化。final修饰方法如下所示,经过修饰的方法,不可被重写,这里我们也注意到原创 2023-12-14 08:56:43 · 1120 阅读 · 0 评论 -
来聊聊CAS
CAS全称,是一种无锁编程算法,即比较当前的值与旧值是否相等若相等则进行修改操作(乐观锁机制),该类常用于多线程共享变量的修改操作。而其底层实现也是基于硬件平台的汇编指令,JVM只是封装其调用仅此而已。而本文会基于以下大纲展开对CAS的探讨。AtomicBoolean: 原子更新布尔类型。AtomicInteger: 原子更新整型。AtomicLong: 原子更新长整型。AtomicIntegerFieldUpdater: 原子更新整型的字段的更新器。原创 2023-12-15 08:36:37 · 1985 阅读 · 0 评论 -
JUC包下各种锁使用详解
相对之下公平锁由于是有序执行,所以相对非公平锁来说执行更慢,吞吐量更小一些。而非公平锁可以在特定场景下实现插队,所以很有可能出现某些线程被频繁插队而导致"线程饥饿"的情况。原创 2022-02-03 20:21:15 · 1686 阅读 · 3 评论 -
Java线程池详解
可以看到我们提交的任务是没有返回值的,而我们提交任务时却用到了submit。查看调用发现,原来后台有一个处理字符串并将内容写入到文本文件的操作,综合来看相当于一个计算型任务,由于这个任务不是很经常出现,所以开发者就设置两个线程,并且为了让任务能够正确完成,拒绝策略也是使用CallerRunsPolicy,让多出来的任务用调用者线程来执行。所以我们建议,对于线程池的中的任务尽可能不要用异常来处理逻辑,对于可以预见的异常,我们建议手动处理返回,避免线程销毁再创建的开销。原创 2022-01-30 10:24:59 · 2512 阅读 · 0 评论