VB.NET中Interlocked相关代码是否为原子块?多线程场景咨询
关于多线程调用PublishUpdateNotification的几个问题解答
这行代码会作为原子块执行吗?
If Interlocked.Increment(WaitingThreadCount) > 1 Then Exit Sub 这行不是原子操作块。只有Interlocked.Increment本身是原子的——它能保证多个线程同时调用时,WaitingThreadCount的递增不会出现竞态问题,但后面的判断(>1)和Exit Sub是单独的步骤,线程在递增完成后、判断前确实可能被上下文切换打断。
会不会出现两个线程都判断值为2并退出?
绝对不会。因为Interlocked.Increment的返回值是当前线程完成递增后的结果,每个线程拿到的是自己操作后的数值:
- 第一个线程调用时,
WaitingThreadCount从0变成1,返回值是1,判断1>1不成立,会继续启动任务执行通知。 - 第二个线程调用时,
WaitingThreadCount已经是1,递增后变成2,返回值是2,判断2>1成立,直接退出。
不管上下文切换什么时候发生,两个线程的判断都是基于各自拿到的返回值,不可能出现都判断为2的情况。
需要把判断放在SyncLock里吗?
不需要。Interlocked.Increment已经搞定了递增的原子性,而判断逻辑用的是每个线程自己拿到的返回值,完全不需要额外加锁,加了反而会影响性能。
重要提醒:你的代码有个致命漏洞
目前的代码里,WaitingThreadCount只增不减——DeliverTheNotifications执行完后没有对计数器做递减操作。这会导致计数器越来越大,之后所有调用PublishUpdateNotification的线程都会直接退出,永远没法再触发通知了。
必须在通知执行完成后调用Interlocked.Decrement(WaitingThreadCount),比如:
Private Sub DeliverTheNotifications() Try ' 这里写你的通知发送逻辑 Finally ' 不管执行成功还是失败,都要把计数器减回去 Interlocked.Decrement(WaitingThreadCount) End Try End Sub
内容的提问来源于stack exchange,提问作者CodeAdze
相关产品推荐
相关产品推荐

