文章目录
攻克并发编程与高并发的难题
一、课程特点
1、并发引入
package com.mmall.concurrency.example.count;
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;
@Slf4j
@NotThreadSafe
public class CountExample1
{
// 请求总数
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", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("count:{}", count);
}
private static void add() {
count++;
}
}
在多线程的并非环境下,如果不采取一些手段,结果很有可能是错的。
2、并发、高并发概念
并发:同时拥有两个或者两个以上的线程,如果程序在单核处理器上运行,多个线程将交替换入或者换出内存,这些线程是同时“存在”的,每个线程都处于执行过程中的某个状态,如果运行在多核处理器上,此时,程序中的每个线程都将分配到一个处理器核上,因此可以同时运行。
高并发:高并发树互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。
3、CPU多级缓存
CPU核心和高速缓存之间有一个快速通道 。
主存和高速缓存都连载系统主件上。
高速缓存和主存之间的速度差异很大。直到加入另一级缓存,新加的缓存比上一级缓存大但是更慢。
4、为什么需要CPU多级缓存
为什么需要cpu缓存:CPU的频率实在太快了,快到主存跟不上,这样在处理器时钟周期内,CPU常常需要等待主存,浪费资源。所以cache的出现,是为了缓解CPU和内存之间速度的不匹配问题。(结构:CPU-》cache-〉memory)
cache的出现,是为了缓解CPU和内存之间速度的不匹配问题,因为CPU速度快,导致CPU等到主存。
5、CPU多级缓存意义
缓存比主存小很多。
CPU cache有什么意义:
- 时间局部性:如果某个数据被访问,那么在不久的将来它有可能被再次访问。
- 空间局部性:如果某个数据被访问,那么与他相邻的数据很快也可能被访问。
6、CPU多级缓存-缓存一致性(MESI协议)
- 用于保证CPU cache之间缓存共享数据的一致。
定义了Cache Line的四种状态,而CPU对Cache的操作可能会导致不一样的状态,因此缓存控制器监听到本地操作和远程操作,需要对地址一致的Cache Line做出一定的修改,从而保证在多个缓存之间数据的一致性。
7、MESI四种状态
Modified:被修改
指的是该缓存行的值被缓存在CPU的缓存中,并且是被修改过的,因此它与主存中的数据是不一致的,该缓存行的内存需要在未来某个时间点写回主存。这个时间点是在允许其他CPU读取主存中相应的数据之前。当被写回主存后,该缓存行的状态被改成E。
Exclusive:独享的
独享的状态指的是缓存行只被缓存在该CPU的缓存中,它是未被修改的,和主存中的数据一致。 这个状态可以在任何时刻当有其他CPU读取该内存时,变成共享状态。同样的,当CPU修改缓存行的内容时,该状态编程Modified状态 。
Shared:共享
Shared意味着该缓存行可能被多个CPU进行缓存,并且该缓存中的数据与主存中的数据是一致的,当有一个CPU修改该缓存行的时候,其他CPU中该缓存行是可以被作废的,变成Invalid状态。
Invalid:无效的
表示有其他CPU修改了该缓存行。
8、四种操作
local read:表示读本地缓存中的数据,
local write:表示将数据写到本地缓存里面
remote read:读取内存中的数据
remote write:将数据写回主存。
在一个典型的多核系统中,每个核都有自己的缓存来共享主存数据,每个相应的CPU都会发出读写请求,而缓存的目的是为了减少CPU读写共享主存的次数。
9、CPU多级缓存-CPU乱序执行优化
指的是处理器为了提高运算速度而做出违背代码原有顺序的优化。
二、Java内存模型(JMM)
规定了一个线程如何和何时可以看到其他线程修改过的共享变量的值。
由于计算机的主存和处理器运算速度之间存在几个数量级的差距, 所以现在的计算机系统就不得不加入一层读写速度都尽可能接近处理器速度的高级缓存来作为内存与处理器之间的缓冲,将运算要使用到的数据复制到缓存中,让运算能够快速进行,当运算结束后,再将结果同步回内存中,这样处理器就不需要等待缓慢的内存读写。
每个线程都有一个私有的本地内存。
1、Java内存模型-同步八种操作
2、Java内存模型-同步规则