并发 十月 21, 2020

并发编程之伪共享

文章字数 1.7k 阅读约需 2 mins.

为了解决计算机系统中主内存与CPU之间运行速度差问题,会在CPU与主内存之间添加一级或者多级高速缓冲存储器(Cache)。在Cache内部是按行存储的,其中每一行称为一个Cache行。Cache行是Cache与主内存进行数据交换的单位,Cache行的大小一般为2的幂次数字节。

当CPU访问某个变量时,首先会去看CPU Cache内是否有该变量,如果有则直接从中获取,否则就去主内存里面获取该变量,然后把该变量所在内存区域的一个Cache行大小的内存复制到Cache中。同一时间只能有一个线程操作缓存行。

当多个线程同时修改一个缓存行里面的多个变量时,由于同时只能有一个线程操作缓存行,所以相比将每...

查看全文

并发 三月 08, 2020

并发编程之volatile

文章字数 1.6k 阅读约需 1 mins.

我们首先来看看在多线程下处理共享变量时Java的内存模型:

Java内存模型规定,将所有的变量都存放在主内存中,当线程使用变量时,会把主内存里面的变量复制到自己的工作空间或者叫作工作内存,线程读写变量时操作的是自己工作内存中的变量。

synchronized块是Java提供的一种原子性内置锁,线程的执行代码在进入synchronized代码块前会自动获取内部锁,这时候其他线程访问该同步代码块时会被阻塞挂起。拿到内部锁的线程会在正常退出同步代码块或者抛出异常后或者在同步块内调用了该内置锁资源的wait...

查看全文

并发 二月 15, 2020

并发编程之Happens-Before原则

文章字数 1.6k 阅读约需 1 mins.

JVM定义的Happens-Before原则是一组偏序关系:对于两个操作A和B,这两个操作可以在不同的线程中执行。如果A Happens-Before B,那么可以保证,当A操作执行完后,A操作的执行结果对B操作是可见的。
Happens-Before的规则包括:

  • 程序顺序规则
  • 锁定规则
  • volatile变量规则
  • 线程启动规则
  • 线程结束规则
  • 中断规则
  • 终结器规则
  • 传递性规则

程序顺序规则

在一个线程内部,按照程序代码的书写顺序,书写在前面的代码操作Happens-Before书写在后面的代码操作...

查看全文

并发 九月 05, 2019

并发编程之LockSupport

文章字数 2.6k 阅读约需 2 mins.

LockSupport提供的park/unpark是以线程的角度来设计,真正解耦了线程之间的同步。

  • park()方法,对当前线程执行阻塞操作,直到获取到可用许可后才解除阻塞,也就相当于当前线程进入阻塞状态。

    park 方法还可以在其他任何时间“毫无理由”地返回,因此通常必须在重新检查返回条件的循环里调用此方法。park不会释放当前线程占有的锁资源。

  • parkNanos(long)方法,对当前线程执行阻塞操作,等待获取到可用许可后才解除阻塞,最大的等待时间由传入的参数来指定,一旦超过最大时...

查看全文

并发 九月 05, 2019

并发编程之AQS原理剖析

文章字数 4.4k 阅读约需 4 mins.

AQS全称是AbstractQueuedSynchronizer,即抽象同步队列。下面看一下AQS的类图结构:

在AQS中维持了一个volatile修饰的单一共享状态state,来实现同步器同步。其更新采用乐观锁思想的CAS算法。

CLH(Craig, Landin, and Hagersten locks) 同步队列 是一个FIFO双向队列,其内部通过节点head和tail记录队首和队尾元素,队列元素的类型为Node。AQS依赖它来完成同步状态state的管理,当前线程如果获取同步状态失败时...

查看全文

并发 七月 15, 2019

并发编程之上下文切换

文章字数 1.3k 阅读约需 1 mins.

CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态。所以任务从保存到再加载的过程就是一次上下文切换。

上下文切换过高,会导致CPU像个搬运工,频繁在寄存器和运行队列直接奔波 ,更多的时间花在了线程切换,而不是真正工作的线程上。直接的消耗包括CPU寄存器需要保存和加载,系统调度器的代码需要执行。间接消耗在于多核 cache之间的共享数据。

  • 使用Lmbench可以测量上下文切...
查看全文
0%