问题标签 [interlocked]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
8565 浏览

java - Java 相当于 .Net 的 Interlocked 类是什么?

如何在 Java 中以原子方式和线程安全地修改 int?

原子增量、测试和设置等...?

0 投票
2 回答
8589 浏览

c# - 用于增加/模仿布尔值的互锁,这安全吗?

我只是想知道一个开发人员(后来离开)的代码是否可以,我认为他想避免加锁。这与仅使用直接锁定之间是否存在性能差异?

我在想这样的事情用锁会更容易吗?它确实会被多个线程使用,因此决定使用锁定/互锁的原因。

0 投票
1 回答
451 浏览

c# - Interlocked.Exchange 不能与泛型一起使用?

我正在编写一个需要使用互锁的通用类。

这不会编译。那么我是否被迫使用 Exchange(Object, Object) 而不是 MSDN 建议不要那样使用它?

0 投票
4 回答
6192 浏览

winapi - 原子 x86 指令与 MS 的 InterlockedCompareExchange 文档的对齐要求?

Microsoft 提供了InterlockedCompareExchange执行原子比较和交换操作的功能。还有一个内在的。_InterlockedCompareExchange

在 x86 上,这些是使用lock cmpxchg指令实现的。

但是,通过阅读有关这三种方法的文档,他们似乎并没有就对齐要求达成一致。

英特尔的参考手册没有提到对齐(除了如果启用对齐检查并进行未对齐的内存引用,则会生成异常)

我还查找了lock前缀,其中明确指出

LOCK 前缀的完整性不受内存字段对齐的影响。

(强调我的)

所以英特尔似乎说对齐是无关紧要的。无论如何,操作都是原子的。

_InterlockedCompareExchange内在文档也没有说明对齐,但是该InterlockedCompareExchange 函数指出

此函数的参数必须在 32 位边界上对齐;否则,该函数将在多处理器 x86 系统和任何非 x86 系统上运行不可预测。

那么给了什么?对齐要求是否InterlockedCompareExchange只是为了确保该功能即使在cmpxchg指令不可用的 486 之前的 CPU 上也能正常工作?根据上述信息,这似乎很可能,但在我依赖它之前我想确定一下。:)

或者ISA是否需要对齐来保证原子性,而我只是在英特尔的参考手册中寻找错误的地方?

0 投票
6 回答
2898 浏览

deadlock - Is the C# "lock" construct rendered obsolete by Interlocked.CompareExchange?

Summary:

It seems to me that:

  1. wrapping fields representing a logical state into a single immutable consumable object
  2. updating the object's authoritative reference with a call to Interlocked.CompareExchange<T>
  3. and handling update failures appropriately

provides a kind of concurrency that renders the "lock" construct not only unnecessary, but a truly misleading construct that dodges certain realities about concurrency and introduces a host of new problems as a result.

Problem Discussion:

First, let's consider the main problems with using a lock:

  1. Locks cause a performance hit, and must be used in tandem for reading and writing.
  2. Locks block thread execution, hindering concurrency and risking deadlocks.

Consider the ridiculous behavior inspired by the "lock". When the need arises to update a logical set of resources concurrently, we "lock" the set of resources, and we do so via a loosely associated, but dedicated locking object, which otherwise serves no purpose (red flag #1).

We then use the "lock" pattern to mark-off a region of code where a logically consistent state change on a SET of data fields occurs, and yet we shoot ourselves in the foot by mixing the fields with unrelated fields in the same object, while leaving them all mutable and then forcing ourselves into a corner (red flag #2) where we have to also use locks when reading these various fields, so we don't catch them in an inconsistent state.

Clearly, there's a serious problem with that design. It's somewhat unstable, because it requires careful management of the lock objects (locking order, nested locks, coordination among threads, blocking/waiting on a resource in use by another thread that's waiting for you to do something, etc.), which depends on the context. We also hear people talk about how avoiding deadlock is "hard", when it's actually very straightforward: don't steal the shoes of a person you plan on asking to run a race for you!

Solution:

Stop using "lock" altogether. Properly roll your fields into an incorruptible/immutable object representing a consistent state or schema. Perhaps it's simply a pair of dictionaries for converting to and from display-names and internal-identifiers, or maybe it's a head node of a queue containing a value and a link to the next object; whatever it is, wrap it into it's own object and seal it for consistency.

Recognize write or update failure as a possibility, detect it when it occurs, and make a contextually informed decision to retry immediately (or later) or do something else instead of blocking indefinitely.

While blocking seems like a simple way to queue a task that seems like it must be done, not all threads are so dedicated and self-serving that they can afford to do such a thing at the risk of compromising the entire system. Not only is it lazy to serialize things with a "lock", but as a side affect of trying to pretend a write shouldn't fail, you block/freeze your thread, so it sets there unresponsive and useless, forsaking all other responsibilities in its stubborn wait to accomplish what it set out to do some time earlier, ignorant of the fact that assisting others is sometimes necessary for fulfilling it's own responsibilities.

Race conditions are normal when independent, spontaneous actions are occurring simultaneously, but unlike uncontrolled Ethernet collisions, as programmers we have total control over our "system" (i.e. deterministic digital hardware) and its inputs (no matter how random, and how random can a zero or one really be?) and outputs, and the memory that stores our system's state, so livelock should be a non-issue; furthermore, we have atomic operations with memory barriers that resolve the fact that there may be many processors operating concurrently.

To summarize:

  1. Grab the current state object, consume its data, and construct a new state.
  2. Realize that other active threads will be doing the very same thing, and may beat you to it, but all observe an authoritative reference point representing the "current" state.
  3. Use Interlocked.CompareExchange to simultaneously see if the state object you based your work on is still the most current state, and replace it with your new one, otherwise fail (because another thread finished first) and take appropriate corrective action.

The most important part is how you handle the failure and get back on your horse. This is where we avoid livelocks, thinking too much and not doing enough or doing the right thing. I would say that locks create the illusion that you'll never fall off your horse, despite riding in a stampede, and while a thread daydreams in such a fantasy land, the rest of the system can fall apart and crash and burn.


So, is there something the "lock" construct can do that can't be achieved (better, in a less unstable fashion) with a lock-free implementation using CompareExchange and immutable logical state objects?

All of this is a realization I've come to on my own after dealing with locks intensely, but after some searching, in another thread Is lock free multithreaded programming making anything easier?, someone mentions that lock-free programming is going to be very important when we face highly parallel systems with hundreds of processors, were we cannot afford to use highly contended locks.

0 投票
2 回答
2653 浏览

winapi - Interlocked* 函数对共享内存有用吗?

两个 Windows 进程将内存映射到同一个共享文件。如果文件包含计数器,是否适合使用Interlocked*函数(如InterlockedIncrement)来更新这些计数器?那些会跨进程同步访问吗?还是我需要使用更重的东西,比如互斥体?或者也许共享内存机制本身可以确保一致的视图。

0 投票
5 回答
1997 浏览

c# - 与使用 Interlocked 类相比,使用 volatile 关键字有什么优势吗?

换句话说,我可以用普通变量和 Interlocked 类无法解决的 volatile 变量做一些事情吗?

0 投票
3 回答
163 浏览

multithreading - 线程和不安全变量

我在这里列出了代码:Threading and Sockets

这个问题的答案是isListeningvolatile. 正如我所说,该修饰符允许我从另一个线程访问变量。读完MSDN后,我意识到我是从下面新创建的线程进程中读取isListening。

所以,我现在的问题:

  • volatile首选方法,因为我基本上是在对变量发出非线程安全请求吗?我已经阅读了有关 Interlocked 类的信息,并想知道在我的代码中使用它是否会更好。Interlocked 看起来与lock(myObj)正在做的事情相似——但具有更多的“天赋”和控制力。我知道简单地应用一个lock(myObj)代码块isListening是行不通的。

  • 我应该实现 Interlocked 类吗?

感谢您的时间和回复。

0 投票
3 回答
1818 浏览

c# - 联锁交换和垃圾收集的安全

我有一个从两个线程访问的对象。一个线程在返回值的对象上调用一个长时间运行的成员函数。第二个线程更新用于产生该值的对象。

如果我在第一个线程执行时调用 Interlock.Exchange 从第二个线程替换对象: 1. 旧线程的自身是否会保留对原始对象的引用。2. 是否存在原始对象被垃圾回收的风险?

这是否保证总是打印“旧”?谢谢。

0 投票
4 回答
1675 浏览

c++ - Win32 C++ 中的无锁双端队列

我对无锁数据结构很陌生,所以对于我编写的练习(我希望用作)一个有界无锁双端队列(还没有调整大小,只是想让基本案例工作)。我只是想从知道他们在做什么的人那里得到一些确认,以确认我是否有正确的想法和/或如何改进这一点。