并发截图版2

并发截图版2_第1张图片

先找L1缓存,再找L2缓存,再找L3缓存。
并发截图版2_第2张图片

缓存是按块来读的。缓存块的大小叫做缓存行,固定大小64字节。
并发截图版2_第3张图片

缓存一致性:缓存行在其他核更新时,本缓存如何更新?

缓存行的4中状态。英特尔CPU使用MESI缓存一致性协议。

并发截图版2_第4张图片
并发截图版2_第5张图片
花3s时间。
对比:
并发截图版2_第6张图片
并发截图版2_第7张图片
只花了1.2s。

说明:两个值非常近时,多线程访问速度可能低。
并发截图版2_第8张图片
加入填充后,x不可能与其他变量在同一个缓存行。因此改变时不需要通知其他缓存行。

有的源码如下:
并发截图版2_第9张图片
添加了无效字段的填充。


volatile:1.线程可见性
2.禁止重排序。


cpu速度是内存的100倍。


并发截图版2_第10张图片
并发截图版2_第11张图片
并发截图版2_第12张图片
原因是CPU会乱序执行。


DCL单例要不要加volatile。



DCL:Double Check Lock

这个单例还挺不错的。
并发截图版2_第13张图片

并发截图版2_第14张图片
并发截图版2_第15张图片
并发截图版2_第16张图片
并发截图版2_第17张图片
经典的DCL写法。以下写法是完美的。很多代码都会用。
并发截图版2_第18张图片
先判断的时间非常短,比直接上锁快很多。
并发截图版2_第19张图片
注意上边有一个volatile,必须加!!!
并发截图版2_第20张图片


读读;写写;读写;写读;

并发截图版2_第21张图片
并发截图版2_第22张图片

并发截图版2_第23张图片
1.Runnable线程没有返回值。
2.Callable有返回值,返回值是Future。Future拿到结果需要阻塞。
3.Google的包:ListenableFuture。这个可以完美解决。
4.jdk1.8学习ListenableFuture,诞生了CompleteFuture,比ListenableFuture更叼。

并发截图版2_第24张图片
并发截图版2_第25张图片
中断时需要cancel方法。

你可能感兴趣的:(#,多线程)