侧边栏壁纸
博主头像
意义Meaning

每天过的都要有意义

  • 累计撰写 10 篇文章
  • 累计创建 6 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

并发编程的三大特性

意义Meaning
2024-11-16 / 0 评论 / 0 点赞 / 19 阅读 / 0 字
温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

1.1 并发编程的三大特性

可见性

有序性

原子性

1.1.1.1 可见性

话不多说,先看下面的代码

public class test01 {
    public static long COUNT = 10_0000_0000L;
    private static class T {
        // private long p1,p2,p3,p4,p5,p6,p7;
        public long x = 0L;
        // private long p9,p10,p11,p12,p13,p14,p15;
    }

    public static T[] arr = new T[2];
    static {
        arr[0] = new T();
        arr[1] = new T();
    }

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(2);
        Thread t1 = new Thread(()->{
            for(long i = 0 ; i < COUNT ; i++){
                arr[0].x = i;
            }
            countDownLatch.countDown();
        });
        Thread t2 = new Thread(()->{
            for(long i = 0 ; i < COUNT ; i++){
                arr[1].x = i;
            }
            countDownLatch.countDown();
        });
        final long start = System.nanoTime();
        t1.start();
        t2.start();
        countDownLatch.await();
        System.out.println((System.nanoTime() - start) / 1000 );
    }

}

该代码执行完所花费的时间为:

然而把该代码中的注释放开后,所花费的时间为:

可以看到,我们多声明了几个变量,反而执行时间却变快了。 这是为什么呢?

其原因是计算机底层在运行程序时,每一条指令都会在CPU中去执行。如果cpu每次都要从内存中去取数据,那么等待的时间肯定是很长的。所以就有了CPU高速缓存(Cache Memory)。

有了CPU高速缓存虽然解决了效率问题,但是它会带来一个新的问题:数据一致性。在程序运行中,会将运行所需要的数据复制一份到CPU高速缓存中,在进行运算时CPU不再与主存打交道,而是直接从高速缓存中读写数据,只有当运行结束后才会将数据刷新到主存中。

解决缓存一致性方案有两种:

  • 通过在总线加LOCK锁的方式

  • 通过缓存一致性协议

缓存一致性协议(不同的cpu厂商有着不同的缓存一致性协议)

存在的意义:CPU高速缓存是为了解决CPU速率和主存访问速率差距过大问题。

一般我们使用的是L1、L2、L3 三级缓存

但要是我使用一个数据,就去内存取一个写入缓存里,还不如不使用缓存呢,这样反而更麻烦了。所以它在取数据的时候,会把该条数据周边的数据也一并取出来。那么一次取多少数据比较合适呢?

答案是 取64个字节

每一次存到缓存中的64个字节称为缓存行

那么L1缓存中将数据改变了,我们该如何通知其他的缓存在更新数据呢? 这个问题也就是并发编程的可见性特征。

介绍这么多了,下面来看我们开头执行的这个代码。

如果我们只声明了一个X变量,那么t1、t2线程在执行时cpu存储的缓存行中,大概率X是在一起的,那么cpu1改了数据,还要去通知更新cpu2的缓存数据。

如果我们在X变量前后声明了几个变量,因为Long类型占8个字节,使得两个X不在同一个缓存行中,那么cpu1修改了数据则不需要去通知更新cpu2的缓存行数据。大大提升了效率。

并发框架Disruptor

Disruptor底层代码中使用的就是缓存一致性协议。

1.1.1.2 有序性

1.1.1.3 原子性

未完待续……

0

评论区