![](https://img-blog.csdnimg.cn/8e24d4584d6f4337a5f6aa4046b919fb.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
并发编程系列
文章平均质量分 80
并发编程系列
兀坐晴窗独饮茶
我的个人博客 http://knightzz.cn/
展开
-
ConcurrentHashMap简单案例
线程安全集合类可以分为三大类:遗留的线程安全集合如Hashtable,Vector使用 Collections 装饰的线程安全集合,如重点介绍Blocking、、Concurrentcas遍历时如果发生了修改,对于非安全容器来讲,使用机制也就是让遍历立刻失败,抛出,不再继续遍历。原创 2022-09-26 14:51:55 · 1053 阅读 · 0 评论 -
CyclicBarrier
循环栅栏,用来进行线程协作,等待线程满足某个计数。构造时设置『计数个数』,每个线程执行到某个需要“同步”的时刻调用 await() 方法进行等待,当等待的线程数满足『计数个数』时,继续执行功能和 countdownlatch 一样, 但是 CyclicBarrier 可以循环使用。原创 2022-09-25 14:33:20 · 93 阅读 · 0 评论 -
Semaphore
semaphore [ˈsɛməˌfɔr] 信号量,用来限制能同时访问共享资源的线程上限....................原创 2022-09-23 18:56:32 · 345 阅读 · 0 评论 -
ReentrantLock读写锁源码解析
事情还没完,在 setHeadAndPropagate 方法内还会检查下一个节点是否是 shared,如果是则调用 doReleaseShared() 将 head 的状态从 -1 改为 0 并唤醒老二,这时 t3 在 doAcquireShared 内。t3 进入 sync.releaseShared(1) 中,调用 tryReleaseShared(1) 让计数减一,这回计数为零了,进入 doReleaseShared() 将头节点从 -1 改为 0 并唤醒老二,即。的低 16 位,而读锁 使用的是。原创 2022-09-23 14:48:31 · 71 阅读 · 0 评论 -
AQS基本介绍
AQS是一个用来构建锁和同步器的框架,使用AQS能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的,Semaphore,其他的诸如,,FutureTask等等皆是基于AQS的。当然,我们自己也能利用AQS非常轻松容易地构造出符合我们自己需求的同步器。AQS 全称是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架独占锁是不可重入锁 , 已经获得锁的话, 再次请求获得锁会导致死锁./*** 独占锁 同步器类。原创 2022-09-23 14:45:03 · 304 阅读 · 0 评论 -
StampedLock
该类自 JDK 8 加入,是为了进一步优化读性能,它的特点是在使用读锁、写锁时都必须配合戳使用StampedLock提供三种模式的读写锁,分别为写锁、悲观读锁、乐观读锁。并且是写写互斥、读写互斥、读读共享。原创 2022-09-23 14:44:08 · 302 阅读 · 0 评论 -
ReentrantLock读写锁源码解析
事情还没完,在 setHeadAndPropagate 方法内还会检查下一个节点是否是 shared,如果是则调用 doReleaseShared() 将 head 的状态从 -1 改为 0 并唤醒老二,这时 t3 在 doAcquireShared 内。t3 进入 sync.releaseShared(1) 中,调用 tryReleaseShared(1) 让计数减一,这回计数为零了,进入 doReleaseShared() 将头节点从 -1 改为 0 并唤醒老二,即。的低 16 位,而读锁 使用的是。原创 2022-09-23 14:43:31 · 222 阅读 · 0 评论 -
ReentrantLock读写锁
使用读写锁保证缓存一致性。原创 2022-09-23 14:42:52 · 346 阅读 · 0 评论 -
ReentrantLock源码解析
ReentrantLock,意思是“可重入锁”,关于可重入锁的概念在下一节讲述。ReentrantLock是唯一实现了Lock接口的类,并且ReentrantLock提供了更多的方法。基本语法上,ReentrantLock与synchronized很相似,它们都具备一样的线程重入特性,只是代码写法上有点区别而已。一个表现为API层面的互斥锁(Lock),一个表现为原生语法层面的互斥锁(synchronized)。原创 2022-09-18 21:11:27 · 289 阅读 · 0 评论 -
Fork&&Join
Fork/Join是 JDK 1.7 加入的新的线程池实现,它体现的是一种分治思想,适用于能够进行任务拆分的 cpu 密集型运算所谓的任务拆分,是将一个大任务拆分为算法上相同的小任务,直至不能拆分可以直接求解。跟递归相关的一些计算,如归并排序、斐波那契数列、都可以用分治思想进行求解Fork/Join在分治的基础上加入了多线程,可以把每个任务的分解和合并交给不同的线程来完成,进一步提升了运算效率Fork/Join默认会创建与 cpu 核心数大小相同的线程池提交给 Fork/Join 线程池的任务需要继承。原创 2022-09-04 20:22:51 · 67 阅读 · 0 评论 -
任务调度线程池
的优点在于简单易用,但由于所有任务都是由同一个线程来调度,因此所有任务都是串行执行的,同一时间只能有一个任务在执行,前一个任务的延迟或异常都将会影响到之后的任务。整个线程池表现为:线程数固定,任务数多于线程数时,会放入无界队列排队。的时候 task1 和 task2 都要开始执行, 但是由于 Timer 内只有一个线程来顺序执行队列中的任务。可以看到两个任务是同一时间执行的, 并不会因为某个任务执行时间慢影响其他的任务。所以 , 当上一个任务延时的情况下, 就会影响下一个任务的执行。原创 2022-09-03 17:51:02 · 331 阅读 · 0 评论 -
异步模式之工作线程
例如,海底捞的服务员(线程),轮流处理每位客人的点餐(任务),如果为每位客人都配一名专属的服务员,那么成本就太高了(对比另一种多线程设计模式:Thread-Per-Message)注意,不同任务类型应该使用不同的线程池,这样能够避免饥饿,并能提升效率例如,如果一个餐馆的工人既要招呼客人(任务类型A),又要到后厨做菜(任务类型B)显然效率不咋地,分成服务员(线程池A)与厨师(线程池B)更为合理。原创 2022-09-03 17:50:06 · 141 阅读 · 0 评论 -
ThreadPoolExecutor详解
当线程数达到 corePoolSize 并没有线程空闲,这时再加入任务,新加的任务会被加入workQueue 队列排队,直到有空闲的线程。如果队列选择了有界队列,那么任务超过了队列大小时,会创建 maximumPoolSize - corePoolSize 数目的线程来救急。自己创建一个单线程串行执行任务,如果任务执行失败而终止那么没有任何补救措施,而线程池还会新建一个线程,保证池的正常工作。线程池中刚开始没有线程,当一个任务提交给线程池后,线程池会创建一个新线程来执行任务。...原创 2022-08-29 18:04:10 · 542 阅读 · 0 评论 -
自定义简单连接池
实现基本的获取连接和归还连接的功能} // 省略实现的部分 }以上实现没有考虑:连接的动态增长与收缩连接保活(可用性检测)等待超时处理分布式 hash对于关系型数据库,有比较成熟的连接池实现,例如c3p0, druid等 对于更通用的对象池,可以考虑使用apachecommons pool,例如redis连接池可以参考jedis中关于连接池的实现。原创 2022-08-20 20:27:42 · 389 阅读 · 0 评论 -
共享变量之不可变对象与保护性拷贝!
主要内容 :不可变类的使用不可变类设计无状态类设计。原创 2022-08-18 18:42:51 · 156 阅读 · 0 评论 -
longAdder源码解析
LongAdder 是并发大师 @author Doug Lea (大哥李)的作品,设计的非常精巧LongAdder 类有几个关键域// 累加单元数组, 懒惰初始化 transient volatile Cell [ ] cells;// 基础值, 如果没有竞争, 则用 cas 累加这个域 transient volatile long base;// 在 cells 创建或扩容时, 置为 1, 表示加锁 transient volatile int cellsBusy;无竞争状态。...原创 2022-08-16 17:25:08 · 245 阅读 · 0 评论 -
volatile原理
double-checked locking 单例模式为例。原创 2022-08-06 15:23:21 · 106 阅读 · 0 评论 -
happens-before规则与线程单例安全习题
happens-before 规定了对共享变量的写操作对其它线程的读操作可见,它是可见性与有序性的一套规则总结,抛开以下 happens-before 规则,JMM 并不能保证一个线程对共享变量的写,对于其它线程对该共享变量的读可见线程对 变量的写,对接下来其它线程对该变量的读可见线程 前对变量的写,对该线程开始后对该变量的读可见线程结束前对变量的写,对其它线程得知它结束后的读可见(比如其它线程调用 或 等待它结束)线程 t1 打断 t2()前对变量的写,对于其他线程得知原创 2022-08-06 15:20:26 · 138 阅读 · 0 评论 -
指令重排以及案例
借助 java 并发压测工具 jcstress https://wiki.openjdk.java.net/display/CodeTools/jcstress。JVM 会在不影响正确性的前提下,可以调整语句的执行顺序,思考下面一段代码。可以看到上面的结果, 指令重排出现的概率很低, 我是没试出来。比如 : 调整为 下面的 , 最终的结果也不会发生变化。在不改变程序结果的前提下,这些指令的各个阶段可以通过。指令重排的前提是,重排指令不能影响结果,例如。生成对应的项目后, 我们就可以添加相应的代码。...原创 2022-08-03 13:20:09 · 4271 阅读 · 0 评论 -
模式之固定与交替顺序执行
park和unpark方法比较灵活,他俩谁先调用,谁后调用无所谓。并且是以线程为单位进行『暂停』和恢复,不需要。原创 2022-07-25 09:42:15 · 107 阅读 · 0 评论 -
ReentrantLock 可重入锁
ReentrantLock相对于synchronized它具备如下特点可中断可以设置超时时间可以设置为公平锁支持多个条件变量与synchronized一样,都支持可重入//获取锁reentrantLock.lock();try{//临界区}finally{//释放锁reentrantLock.unlock();}中也有条件变量,就是waitSet休息室,当条件不满足时进入waitSet等待的条件变量比。...原创 2022-07-23 17:45:12 · 388 阅读 · 0 评论 -
synchronized锁原理优化
互换LockRecord的地址和MarkWord的内容ObjectRef指向锁地址轻量级锁没办法处理不同线程竞争锁的问题如果加锁失败,说明别的线程把这个锁占了就把轻量级锁升级称重量级申请一个Monitor对象让原本指向锁对象的ObjectReference重新指向重量级锁对象Monitor当前线程自己进入Monitor的EntryListBLOCKED。......原创 2022-07-14 21:40:04 · 221 阅读 · 0 评论 -
从字节码角度理解 synchronized原理
可以使用 jclasslib 插件查看字节码可可以使用原创 2022-07-08 22:18:40 · 170 阅读 · 0 评论 -
Monitor原理
Java 中的 Monitor 机制What’s a monitor in Java?浅析操作系统同步原语解析Java对象在内存空间中的构成以及对象头的概念对象头包括了关于堆对象的布局、类型、GC状态、同步状态和标识哈希码的基本信息。Java对象和vm内部对象都有一个共同的对象头格式。它是Java对象和虚拟机内部对象都有的共同格式,由两个字(计算机术语)组成。另外,如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小原创 2022-07-08 18:13:41 · 219 阅读 · 0 评论 -
卖票与转账案例
上面代码比较容易出现问题的地方在 :判断的地方容易出现超买, 因为所有线程共享同一个对象的 count线程1线程2成员变量countget count = 2调用sell(amount=1), 出售1张票count > amount, 满足条件线程上下文切换get count = 2调用sell(amount=2), 出售2张票count >= amount, 满足条件count -2 = 0put count = 0线程上下文切换count - 1 = 1put count = 1线程1线程2成员变量c原创 2022-07-08 16:36:34 · 124 阅读 · 0 评论 -
synchronized 解决共享带来的问题
两个线程对初始值为 0 的静态变量一个做自增,一个做自减,各做 5000 次,结果是 0 吗?问题分析以上的结果可能是正数、负数、零。为什么呢?因为 Java 中对静态变量的自增,自减并不是原子操作,要彻底理解,必须从字节码来进行分析例如对于 i++ 而言(i 为静态变量),实际会产生如下的 JVM 字节码指令:而对应 i-- 也是类似:而 Java 的内存模型如下,完成静态变量的自增,自减需要在主存和工作内存中进行数据交换:如果是单线程以上 8 行代码是顺序执行(不会交错)没有问题:[外链图片转存原创 2022-07-03 21:17:08 · 301 阅读 · 0 评论 -
线程常用方法与守护线程
start 方法只是让线程进入就绪,里面代码不一定立刻运行(CPU 的时间片还没分给它)。每个线程对象的start方法只能调用一次,如果调用了多次会出现 IllegalThreadStateException测试代码 :运行结果如上面的运行结果所示 :而使用 执行时, 是 在 主线程执行的, 并没有新开一个线程!代码实例 :执行结果 :可以看到上面的执行结果以及代码 , 当执行 方法以后, 线程的状态从 变成了 总结 :代码示例 :示例图让主线程睡眠的原因是因为 防止 线程还没有睡眠, 线程的状原创 2022-06-28 21:00:02 · 243 阅读 · 0 评论 -
线程运行原理
Java Virtual Machine Stacks (Java 虚拟机栈)具体示例如下 :当我们运行到主线程时, 可以看到只有主线程在活动而当我运行到 位置时 当前的活动栈帧对应着继续运行直到运行到 时可以看到此时有三个栈帧, 活动栈帧是 , 所以代码示例初始状态如下 :执行主方法, 创建 栈帧局部变量表 :继续向下执行, 执行到 方法内是 , 此时注意 :当我们继续向下执行时, 执行到 :当最后一个方法 method2 执行结束后, 会根据返回地址逐步返回, 直到结束...原创 2022-06-20 22:13:58 · 198 阅读 · 1 评论 -
多线程的应用 - 提升效率
基准测试工具选择,使用了比较靠谱的 JMH,它会执行程序预热,执行多次测试并平均cpu 核数限制,有两种思路点击 Add , 添加 groupId : , 然后添加 ArtifactId : 也可以通过maven命令创建创建完成以后记得去pom文件中将java编译版本从1.6修为1.8编写测试代码使用 maven package 打成 jar包然后命令台进入target目录下 , 执行 执行结果如上面所示 : 可以看到效率差了很多, 多线程的执行 耗费 0.022 s , 而单线程耗费 0.0原创 2022-06-19 18:54:30 · 271 阅读 · 0 评论 -
进程与多线程
当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程。进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程(例如记事本、画图、浏览器等),也有的程序只能启动一个实例进程(例如网易云音乐、360 安全卫士等)进程基本上相互独立的,而线程存在于进程内,是进程的一个子集进程拥有共享的资源,如内存空间等,供其内部的线程共享进程间通信较为复杂线程通信相对简单,因为它们共享进程内的内存,一个例子是多个线程可以访问同一个共享变量线程更轻量,线程上下文切换成本一般上要比进程上下文切换低单核 c原创 2022-06-19 18:45:53 · 64 阅读 · 0 评论