![72fbfbb066048a0623a3e18388c585bd.png](https://i-blog.csdnimg.cn/blog_migrate/e787875f086296bde2e02df28318ccad.jpeg)
![0a0a3e5aeb4e931279ae76f875add4ae.png](https://i-blog.csdnimg.cn/blog_migrate/213278bc2bf2a7e141e1823acfb84aa6.jpeg)
![9b6675003af62ce9e837c2cf14038c8b.png](https://i-blog.csdnimg.cn/blog_migrate/0c181fcfe9778a80c28e7ae42c1b234a.jpeg)
1 基本概念
1.1 并发
同时拥有两个或者多个线程,如果程序在单核处理器上运行多个线程将交替地换入或者换出内存,这些线程是同时“存在"的,每个线程都处于执行过程中的某个状态,如果运行在多核处理器上,此时,程序中的每个线程都将分配到一个处理器核上,因此可以同时运行.
1.2 高并发( High Concurrency)
互联网分布式系统架构设计中必须考虑的因素之一,通常是指,通过设计保证系统能够同时并行处理很多请求.
1.3 区别与联系
- 并发: 多个线程操作相同的资源,保证线程安全,合理使用资源
- 高并发:服务能同时处理很多请求,提高程序性能
2 CPU
2.1 CPU 多级缓存
![e13641c8ede02d306919f9e1a9b44d93.png](https://i-blog.csdnimg.cn/blog_migrate/a5467217109a381d371944fdba7190bf.jpeg)
- 为什么需要CPU cache
- CPU的频率太快了,快到主存跟不上
- 如此,在处理器时钟周期内,CPU常常需要等待主存,浪费资源。所以cache的出现,是为了缓解CPU和内存之间速度的不匹配问题(结构:cpu-> cache-> memory ).
- CPU cache的意义
- 1) 时间局部性
- 如果某个数据被访问,那么在不久的将来它很可能被再次访问
- 2) 空间局部性
- 如果某个数据被访问,那么与它相邻的数据很快也可能被访问
2.2 缓存一致性(MESI)
- 用于保证多个 CPU cache 之间缓存共享数据的一致
- M-modified被修改
- 该缓存行只被缓存在该 CPU 的缓存中,并且是被修改过的,与主存中数据是不一致的,需在未来某个时间点写回主存,该时间是允许在其他CPU 读取主存中相应的内存之前,当这里的值被写入主存之后,该缓存行状态变为 E
- E-exclusive独享
- 缓存行只被缓存在该 CPU 的缓存中,未被修改过,与主存中数据一致
- 可在任何时刻当被其他 CPU读取该内存时变成 S 态,被修改时变为 M态
- S-shared共享
- 该缓存行可被多个 CPU 缓存,与主存中数据一致
- I-invalid无效
![f86521354f5edf975660708c7f83e880.png](https://i-blog.csdnimg.cn/blog_migrate/f1d8b193f8e777207a5d0d61bf102ea8.jpeg)
- 乱序执行优化
- 处理器为提高运算速度而做出违背代码原有顺序的优化
- ##并发的优势与风险
![51df49ceb17e9e737ee47d7923014f96.png](https://i-blog.csdnimg.cn/blog_migrate/b99ceb161b322b0b204d11a891971ab2.jpeg)
3 项目准备
3.1 项目初始化
![cd019fe9be1f93741714c6e07516ca61.png](https://i-blog.csdnimg.cn/blog_migrate/c155f0242dba9e693ce7e19315c1800f.jpeg)
![778215119a0c32ce4a901dd5f69ddacd.png](https://i-blog.csdnimg.cn/blog_migrate/9cfeeb6f72fd55f976738077c49d73f8.jpeg)
![92dd56e635ddeeacc46ea61b0da2bfca.png](https://i-blog.csdnimg.cn/blog_migrate/6f1263a92a292c2ff0108c56f93f4ae5.jpeg)
3.2 并发模拟-Jmeter压测
![a566212480b6744c170b5e602218d928.png](https://i-blog.csdnimg.cn/blog_migrate/14d4706b2b4d8ee3d21405380bc0921e.jpeg)
![0c7876d27f250194c9c21015ee4330b5.png](https://i-blog.csdnimg.cn/blog_migrate/bd2a62c2d88b8095735c04e492eb3619.jpeg)
![a7bcba064caf60580d91798d6cae02b5.png](https://i-blog.csdnimg.cn/blog_migrate/85abf2ceec062851016afcd1e4954a57.jpeg)
![65f3912c40320a2151f213e7a02bd1bc.png](https://i-blog.csdnimg.cn/blog_migrate/9c99f816db26af177c705dbb82f52b91.jpeg)
![554c809e133f517f89c38b84a6120b59.png](https://i-blog.csdnimg.cn/blog_migrate/1bd088890ea96cade4bb9b12f4fc0945.jpeg)
3.3 并发模拟-代码
- CountDownLatch
![d0401199106b204eae685c43169a965f.png](https://i-blog.csdnimg.cn/blog_migrate/2ab7c64329918ef7d5e32aaa070453e0.jpeg)
- Semaphore(信号量)
![57b68e18e9b99dd1f5aec139b37204c1.png](https://i-blog.csdnimg.cn/blog_migrate/e9e744aadecfb4c1c1507ae92d9d2e54.jpeg)
- 以上二者通常和线程池搭配
下面开始做并发模拟
package com.mmall.concurrency;import com.mmall.concurrency.annoations.NotThreadSafe;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;/** * @author shishusheng * @date 18/4/1 */@Slf4j@NotThreadSafepublic class ConcurrencyTest { /** * 请求总数 */ public static int clientTotal = 5000; /** * 同时并发执行的线程数 */ public static int threadTotal = 200; public static int count = 0; public static void main(String[] args) throws Exception { //定义线程池 ExecutorService executorService = Executors.newCachedThreadPool(); //定义信号量,给出允许并发的线程数目 final Semaphore semaphore = new Semaphore(threadTotal); //统计计数结果 final CountDownLatch countDownLatch = new CountDownLatch(clientTotal); //将请求放入线程池 for (int i = 0; i < clientTotal ; i++) { executorService.execute(() -> { try { //信号量的获取 semaphore.acquire(); add(); //释放 semaphore.release(); } catch (Exception e) { log.error("exception