【C# 线程】interLocked锁
overview
同步基元分为用户模式和内核模式
用户模式:Iterlocked.Exchange(互锁)、SpinLocked(自旋锁)、易变构造(volatile关键字、
volatile
类、Thread.VolatitleRead|Thread.VolatitleWrite
)、MemoryBarrier。
.net中的System.Threading命名空间的Interlocked类可以为多个线程共享的变量提供原子操作。
经验显示,那些需要在多线程下被保护的资源通常是整型的,而这些被共享的整型值最常见的操作就是增加、减少。Interlocked类提供了一个专门的机制用于完成这些特定的操作。
Iterlocked.Exchange()
不只是原子的,它还具有内存可见性。
所有 方法都生成一个完整的栅栏。因此,您通过访问的字段不需要额外的栅栏。
Interlocked 轻量级锁
Interlocked.Increment(ref value) 数值加一(原子性操作)
Interlocked.Decrement(ref value) 数值减一(原子性操作)
Interlocked.Exchange(ref value1, value2) 交换:把值2赋给值1;返回新值
Interlocked.CompareExchange(ref value1, value2, value3) 实现比较和交换两种功能:值1和值3比较,如果相同,把值2给值1,不相同则不作任何操作;返回原值(多用于判断条件)(示例3中会用到)
Interlocked.MemoryBarrier :按如下方式同步内存存取:执行当前线程的处理器在对指令重新排序时,不能采用先执行 MemoryBarrier() 调用之后的内存存取,再执行 MemoryBarrier() 调用之前的内存存取的方式。Thread.MemoryBarrier 就是包装了它。
个人补充:值刷新当前执行线程的cpu上的store buffer和Invalidate queue都运行完成了.
Interlocked.MemoryBarrierProcessWide:内部执行FlushProcessWriteBuffers函数()。该函数功能刷新正在运行当前进程所有线程的每个处理器的写入队列(store buffer)。该函数为属于当前进程关联一部分的所有处理器生成一个处理器间中断 (IPI)。它保证了在一个处理器上对另一个处理器执行的写入操作的可见性。
个人补充:将当前进程下所有线程所在的cpu上的store buffer和Invalidate queue都运行完成了,所以非常耗费时间 。
注意不要传入 volatile类型。
Interlocked.Add 方法:以原子操作的形式,添加两个整数并用两者的和替换第一个整数。
Add(Int32, Int32)|Add(Int64, Int64)Add|(UInt32, UInt32)|Add(UInt64, UInt64)
对两个 32 位整数进行求和并用和替换第一个整数,上述操作作为一个原子操作完成。
And(Int32, Int32)方法:对两个 32 位带符号整数进行按位“与”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。
Add(Int32, Int32)|Add(Int64, Int64)Add|(UInt32, UInt32)|Add(UInt64, UInt64)
对两个 32 位带符号整数进行按位“与”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。
Interlocked.Or 方法:对两个 32 位带符号整数进行按位“或”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。
Add(Int32, Int32)|Add(Int64, Int64)Add|(UInt32, UInt32)|Add(UInt64, UInt64)
对两个 32 位带符号整数进行按位“或”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。
Interlocked.Read 方法 :返回一个以原子操作形式加载的 64 位值。
Read(Int64) |Read(UInt64)
返回一个以原子操作形式加载的 64 位值。
MemoryBarrierProcessWide方法与“普通”MemoryBarrier方法的区别如下:
正常的memory barrier可以确保当前CPU的读写不能跨越barrier。进程级内存屏障确保了进程中使用的任何CPU的任何读或写操作都不能跨越这个屏障。
如果每个访问数据的线程都使用barrier,那么正常的内存barrier允许合理的共享访问。进程级内存屏障迫使其他cpu与进程内存同步(例如,刷新写缓冲区和同步读缓冲区)。这允许在某些线程上进行非连锁操作,并且仍然有合理的共享访问。
正常的内存屏障的开销很小;正常的连锁操作可能花费不到100个周期。进程级内存屏障非常昂贵。它必须迫使进程中的每个CPU做一些事情,可能要花费数千个周期。
MemoryBarrierProcessWide方法还受到无锁编程的所有微妙之处的影响。然而,当您实际需要调用它时,这个方法可能非常有用,这种情况应该很少见。
该方法封装了对Windows上的FlushProcessWriteBuffers和Linux上的sys_membarrier的调用。
案例来自:
这个案例主要考验对 volatile关键字和内存屏障的理解。
该案例会出乎意料的输出0,0 。为了避免该情况必须使用全内存屏障。
该例子来自:volatile的内存屏障的坑
- using System;
- using System.Threading;
- using System.Threading.Tasks;
- namespace MemoryBarriers
- {
- class Program
- {
- static volatile int x, y, a, b;
- static void Main()
- {
- while (true)
- {
- var t1 = Task.Run(Test1);
- var t2 = Task.Run(Test2);
- Task.WaitAll(t1, t2);
- if (a == 0 && b == 0)
- {
- Console.WriteLine("{0}, {1}", a, b);
- }
- x = y = a = b = 0;
- }
- }
- static void Test1()
- {
- x = 1;
- //方案一 Interlocked.MemoryBarrier();
- //方案二 Interlocked.MemoryBarrierProcessWide();
- a = y;
- }
- static void Test2()
- {
- y = 1;
- //方案一 Interlocked.MemoryBarrier();
- b = x;
- }
- }
- }
【C# 线程】interLocked锁的更多相关文章
- JAVA语言规范-线程和锁章节之同步、等待和通知
JAVA语言规范:线程和锁 1 同步 java编程语言提供了线程间通信的多种机制.这些方法中最基本的是同步化,此方法是使用监视器实现的.JAVA中每个对象与一个监视器相关联,一个线程可以加锁和解锁监视 ...
- GIL与线程互斥锁
GIL 是解释器级别的锁,是限制只有一个原生线程运行,防止多个原生线程之间修改底层的共享数据.而线程互斥锁是防止多个线程同时修改python内存空间的共享数据.
- Java线程:锁
一.锁的原理 Java中每个对象都有一个内置锁,当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行的代码类的当前实例(this实例)有关的锁.获得一个对象的锁也称为获取锁.锁 ...
- (三)juc高级特性——虚假唤醒 / Condition / 按序交替 / ReadWriteLock / 线程八锁
8. 生产者消费者案例-虚假唤醒 参考下面生产者消费者案例: /* * 生产者和消费者案例 */ public class TestProductorAndConsumer { public stat ...
- Java 线程与锁
Synchronization synchronized语法可以获取锁, 当其他线程持有锁的时候该线程想要获取锁将会进入等待状态, 直到没有其他线程持有该锁 显示使用 synchronized (lo ...
- Java线程与锁
概要:线程的实现方法. 线程调度.线程状态及转换.线程安全(5种分类.3种实现方法.锁优化技术) 进程是OS进行资源分配的基本单位,线程是CPU调度的基本单位. 1.线程的实现方法 可参阅 我是一个进 ...
- java多线程 -- 线程八锁
一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了,其它的线程都只能等待,换句话说,某一个时刻内,只能有唯一一个线程去访问这些 ...
- GUC-10 线程八锁
/* * 题目:判断打印的 "one" or "two" ? * * 1. 两个普通同步方法,两个线程,标准打印, 打印? //one two * 2. 新增 ...
- JUC——线程同步锁(锁处理机制简介)
锁处理机制简介 juc的开发框架解决的核心问题是并发访问和数据安全操作问题,当进行并发访问的时候如果对于锁的控制不当,就会造成死锁这样的阻塞问题. 为了解决这样的缺陷,juc里面重新针对于锁的概念进行 ...
- GIL线程全局锁 协程
GIL线程全局锁 线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.对于io密集型任务 ...
随机推荐
- golang中GPM模型原理与调度器设计策略
一.GMP模型原理first: 1. 全局队列:存放待运行的G2. P的本地队列:同全局队列类似,存放待运行的G,存储的数量有限:256个,当创建新的G'时,G'优先加入到P的本地队列,如果队列已满, ...
- golang中将函数当做函数参数使用
package main import ( "fmt" "strings" ) // 使用type关键字让函数变成一个自定义类型 type caseFunc f ...
- 在Excel VBA中写SQL,是一种什么体验
每每提到Excel办公自动化,我们脑海里能想到的就是公式.数据透视表.宏.VBA,这也是我们大部分人数据分析的进阶之路.当我们对于常用VBA技巧已经相当熟练后,往往会有一种"我的VBA知识够 ...
- find -or 用法
find /opt/IBM/WebSphere85/ -name *loggeter* - or -name *loggetter* | xargs rm -rf
- lambda表达式的学习
Lambda表达式 为什么使用lambda表达式 Lambda表达式可以简化我们的代码,使我们只需要关注主要的代码就可以. //测试用的实体类 public class Employee { priv ...
- Hbase 项目
需求分析 1) 微博内容的浏览,数据库表设计 2) 用户社交体现:关注用户,取关用户 3) 拉取关注的人的微博内容 表结构 代码实现 1) 创建命名空间以及表名的定义 2) 创建微博内容表 3) 创 ...
- VMware网络连接模式(桥接、NAT以及仅主机模式的详细介绍和区别)
VMware 桥接模式 VMware桥接模式,也就是将虚拟机的虚拟网络适配器与主机的物理网络适配器进行交接,虚拟机中的虚拟网络适配器可通过主机中的物理网络适配器直接访问到外部网络(例如图中所示的局域网 ...
- Linux中Swap与Memory内存简单介绍 (转)
https://blog.csdn.net/zwan0518/article/details/12059213 一.背景介绍 对于Linux来说,其在服务器市场的使用已经占据了绝对的霸主地位,不可动摇 ...
- Java 内置注解简单理解
感谢原文作者:yejg1212 原文链接 https://www.cnblogs.com/yejg1212/p/3187362.html https://www.cnblogs.com/yejg121 ...
- 恶补Java Swing线程刷新UI机制(由浅到深的参考大佬博文)
1. java中进度条不能更新问题的研究 感谢大佬:https://blog.csdn.net/smartcat86/article/details/2226681 为什么进度条在事件处理过程中不更新 ...