一、问题

1、统计服务器某个接口的访问次数
image.png
accessCount字段表示接口被访问的次数, 每次访问接口的时候就调用一次access()方法,访问次数+1,累积下来,就能统计出接口被访问的次数了
2、如果接口很可能被多个线程同时访问,即access()方法被多个线程调用,次数就会不准确

二、内存概念模型

1、CPU内存模型

1)计算机在执行程序的时候,每条指令都是在CPU中执行的
2)CPU执行指令的过程 会涉及到数据的读取和写入操作
3)数据都存在主存中
4)CPU则是从主存中读取数据进行运算
5)问题:CPU执行速度非常快,比计算机主存读取和存入快很多,会导致CPU执行速度大大下降
image.png

2、针对1 的问题

1)每个CPU会自带一个高速缓冲区
2)运行的时候,将数据从主存先复制到高速缓冲区
3)CPU再基于高速缓冲区进行运算
4)运算结束,再将数据从高速缓冲区刷到主存中
image.png

三、java内存模型

1)JVM启动后,操作系统会为JVM分配一定的空间内存,称为”主内存”
2)JAVA程序的所有工作都是由线程完成,每个线程都分配一块内存,称为”工作内存”
3)java线程在执行过程中,会先将数据从“主内存”中刷到“工作内存”中
4)执行计算等操作
5)把计算结果从 “工作内存”刷到“主内存”中

四、基于java内存模型,分析缓存一致性问题

1、步骤

  1. 从主存中读取accessCount的值
  2. 将accessCount的值进行加1
  3. 将accessCount的值写回主存中

    2、执行

    image.png

image.png
image.png

3、结果

accessCount=1,应该是2才对

4、引申出的并发中的概念-原子性

原子性即一个操作或者多个操作,要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行

5、解决

对应前面的场景,就是如果我们能保证accessCount++这个操作的3个步骤是原子性的,比如线程1开始了第一个步骤,那线程2如果要执行的话那就等着吧,等到线程1把3个步骤都执行完,线程2才能开始第一个步骤。那这样就能解决线程安全的问题了