Interlocked.CompareExchange在if语句中是否具备原子性?
关于Interlocked.CompareExchange线程安全性的解答
你完全不用担心这种情况,核心原因是Interlocked.CompareExchange本身是原子操作——它的"读取当前值+比较+交换(符合条件时)+返回旧值"整个过程是一次性完成的,不会被其他线程打断。
你的拆分理解存在偏差,实际执行逻辑是:
Interlocked.CompareExchange(ref semaphore, 1, 0)会原子性完成三件事:读取semaphore的当前值,判断该值是否等于0,若相等则将semaphore设置为1,最后返回操作前的旧值。- 后续的
== 0比较,是判断这个原子操作返回的旧值,而非读取当前semaphore的最新值。
举个具体场景说明:
- 线程A调用
CompareExchange时,semaphore值为0,原子操作完成后semaphore被设为1,返回旧值0。此时即便其他线程修改semaphore(实际上线程A已经把它设为1,其他线程的CompareExchange会返回1,无法进入代码块),线程A的判断基于返回的旧值0,会正常进入代码块,这是正确的锁抢占逻辑。 - 如果线程B先调用
CompareExchange,抢占到锁(semaphore被设为1,返回0)并进入代码块;线程A再调用时,会读取到当前值1,返回旧值1,判断1==0不成立,不会进入代码块。
另外需要注意:代码末尾的semaphore = 0不是原子操作,若代码块内抛出异常,会导致semaphore一直处于1的状态,引发锁泄漏,但这不会导致多个线程同时进入代码块的问题——只有成功将semaphore从0原子性改为1的线程,才会得到返回值0并进入代码块。
内容的提问来源于stack exchange,提问作者Somecode
相关产品推荐
相关产品推荐

