@@ -128,4 +128,54 @@ AtomicLong是作用是对长整形进行原子操作。而AtomicLongArray的作
128128* Java并发的场景&原因&问题浅谈 https://blog.csdn.net/zangdaiyang1991/article/details/98481346
129129* 什么是CAS https://www.jianshu.com/p/ab2c8fce878b
130130* 一篇看懂Java中的Unsafe类 https://www.jb51.net/article/140726.htm
131- * 浅谈AtomicInteger实现原理 https://www.jianshu.com/p/cea1f9619e8f
131+ * 浅谈AtomicInteger实现原理 https://www.jianshu.com/p/cea1f9619e8f
132+ 并发的三种场景
133+ 分工
134+ 分工是多线程并发最基本的场景,各司其职,完成各自的工作。分工,就是线程各司其职,完成不同的工作。分工,也是有很多模式的。比如有:
135+
136+ 生产者-消费者模式;
137+ MapReduce模式,把工作拆分成多份,多个线程共同完成后,再组合结果,Java8中的stream与Fork/Join就是这种模式的体现;
138+ Thread-Per-Message模式,服务端就是这种模式,收到消息给不同的Thread进行处理
139+ 同步
140+ 有分工就要有同步,不同工人之间要协作,不同线程也是。一个线程的执行条件往往依赖于另一线程的执行结果。
141+
142+ 线程之间最基本的通信机制是管程模式与wait/notify,除此外还有多个工具类,如:
143+
144+ Future及其衍生的工具类FutureTask/CompletableFuture等,可以完成异步编程;
145+ CountDownLatch/CyclicBarrier可以实现特定场景的协作;
146+ Semaphore提供了经典的PV同步原语,还可以作为限流器使用;
147+ ReentrantLock与Condtion,对管程同步的扩展;
148+ 互斥
149+ 多线程访问相同的共享变量,就需要做互斥处理。分工与协作强调的是性能,互斥问题强调的是正确,即线程安全问题。Java解决互斥问题提供了很多思路与工具。
150+
151+ 避免共享,没有共享,没有竞态,就没有伤害,如ThreadLocal;
152+ 没有改变,如果大家都不做改变,都是只读的,一起也没有错;
153+ Copy-on-write,你变你的,我变我的,每变一次都生成新的副本,只要不冲突就可以并行;
154+ CAS,写入前要看一看,有没有物逝人非(变量和自己读取时一样),没有再写入,否则再做一变;
155+ Lock,最终手段,但也不想做得太绝,够用就行,ReadWriteLock/StampedLock,够用就行
156+
157+ 并发问题产生的原因
158+ 缓存导致的可见性问题
159+ 在运行时,同一份数据就出现了两份,一个在内存,一个在CPU缓存。每个CPU中有各自的数据缓存(JMM内存模型)。
160+
161+ 线程切换带来的原子性问题
162+ 计算机看起来可以同时运行多于自身核数的线程,是因为现代操作系统的分时切换机制。分时机制提高了CPU的使用率,也可以保证多线程可以相对公平地获取CPU。但分时机制导致了一个不可避免的问题,就是线程切换。发生线程切换时,被休眠的线程会暂存现场,包括PC(程序计数器)与栈等。等到此线程再次被唤醒,可能发现这个世界已经物是人非了,因为一条高级语言指令可能对应多条CPU指令。
163+
164+ 编译优化带来的有序性问题
165+ JAVA为了优化性能,可能对指令进行重排,这些重排在大部分时候是无害的。但是有些时候,可能导致意想不到的Bug。由重排引起的一个经典问题是双重量检查创建单例。
166+
167+
168+ 并发的三种问题
169+ 安全性问题
170+ 并发程序因为可见性、原子性及有序性问题等导致的正确性问题
171+
172+ 活跃性问题
173+ 指的是某个操作无法执行下去,如死锁等导致的问题
174+
175+ 性能问题
176+ 一般都是由锁的滥用引起的。
177+ 性能方面有三个主要的指标:吞吐、时延及并发量。
178+
179+ 吞吐,指单位时间处理的请求数;
180+ 时延,指单次处理的平均耗时;
181+ 并发,同一时刻可以接入的请求数
0 commit comments