问题标签 [interlocked-increment]
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.
c++ - 使用 InterlockedIncrement64 的引用计数对象的复制构造函数的原子性
我正在努力思考如何确保对象引用计数是线程安全的。
假设有必要的类声明,只是保持简单。这里是拷贝构造函数和析构函数的实现。
这个线程安全吗?如何看到复制构造函数的 intilization 列表,原子与否?这还重要吗?我应该在初始化列表中设置计数的递增值(这可能吗)?
就目前而言,这已经足够好了。我认为它是,否则,我怎么能进入thread1
复制和thread2
同时销毁的场景count == 1
。线程之间必须进行握手,这意味着 thread1 必须在 thread2 的对象超出范围之前完全复制对象,对吗?
在阅读了其中一些回复后,我回去做了一些研究。Boost 非常相似地实现了它们的 shared_ptr。这是析构函数调用。
有些人建议在 boost 文档中明确指出分配不是线程安全的。我同意和不同意。我认为在我的情况下我不同意。我只需要threadA和threadB之间的握手。我认为某些回复中描述的某些问题在这里并不适用(尽管它们是我没有完全考虑过的令人大开眼界的回复)。
示例 ThreadA atach(SharedObject); //通过值传递的共享对象,计数递增等
ThreadB //接受对象,将其添加到共享对象列表中。ThreadB 位于一个计时器上,该计时器向所有 SharedObjects 通知一个事件。在通知之前,列表的副本由关键部分保护。CS被释放,副本被通知。
ThreadA 分离(SharedObject);//从对象列表中删除共享对象
现在,同时 ThreadB 正在对 SharedOjbect 进行单选,并且在 ThreadA 分离所述共享对象之前已经制作了列表的副本。一切都好吗?
c++ - 手动编写多线程循环 - 次优可扩展性
我编写了这个测试应用程序:它经历了从 0 到 9999 的迭代,对于范围内的每个整数,它都会计算一些无用但计算密集型的函数。结果,程序输出函数值的总和。为了让它在多个线程上运行,我使用了 InterlockedIncrement - 如果在增量之后迭代次数 <10000,那么一个线程处理这个迭代,否则它终止。
我想知道为什么它没有像我希望的那样缩放。使用 5 个线程,它运行 8 秒,而单线程运行 36 秒。这提供了约 4.5 的可扩展性。在我对 OpenMP 的实验中(在稍微不同的问题上),我得到了更好的可扩展性。
源代码如下所示。
我在 Phenom II X6 桌面上运行 Windows7 操作系统。不知道其他哪些参数可能是相关的。
你能帮我解释一下这种次优的可扩展性吗?非常感谢。
编辑:附加此测试程序的示例输出(1 和 5 个线程):
c# - 互锁比较交换使用 GreaterThan 或 LessThan 代替相等
该System.Threading.Interlocked
对象允许将加法(减法)和比较作为原子操作。似乎不做相等但也将 GreaterThan/LessThan 作为原子比较的 CompareExchange 将非常有价值。
是 IL的假设Interlocked.GreaterThan
特性还是 CPU 级别的特性?两个都?
缺少任何其他选项,是否可以在 C++ 或直接 IL 代码中创建这样的功能并将该功能公开给 C#?
c# - C# 中的自旋锁。在哪种算法中 SpinLock 是对 Monitor 的更好选择?
可能重复:
为什么每个人都说 SpinLock 更快?
这个问题是关于 SpinLock、Monitor & Interlocked。
我做了 2 个测试来测试 的性能,Monitor
这些测试让我感到困惑。SpinLock
Interlocked
我的困惑特别是关于SpinLock
真正的速度有多快。根据我的测试SpinLock
,它比Monitor
. 但是基于一些文档和文章SpinLock
应该提供性能增益。
现在我想知道在哪些情况下会SpinLock
提高性能?
您可以在下面找到有关我执行的测试的一些详细信息:
在第一次测试中,我创建了几个线程(就像我拥有的许多硬件线程一样)访问同一个共享锁对象,执行非常短的操作(或根本没有操作:这只是一个测试)。
在第二个测试中,我创建了一个元素数组,并且很少有线程随机访问该数组中的元素。每个元素都包含自己的锁定对象:System.Object
for Monitor
test,SpinLock
object for SpinLock
test,对于Interlocked.Increment
,线程使用数组元素内部的int类型的公共变量来执行Interlocked.Increment
操作。
在每个测试中,对共享区域的访问都是循环执行的。每个测试由 3 个例程组成:
- 测试自旋锁
- 测试监视器
- 测试增量.联锁
每次测试都显示SpinLock
比 慢Monitor
。所以,自从我进行了提到的测试以来,困扰我的问题是哪些场景适合于由SpinLock
发布测试代码以提供详细信息:
(这两个测试都是针对 .net 4.5 编译的)
测试 1,线程试图获得对同一个共享锁定对象的独占访问权限
测试2,线程试图获得对数组元素的独占访问权,这些元素是随机挑选的,即低竞争测试
附加测试 3. 测试在单个线程中执行。线程访问锁的最高机会。
据我了解,第三次测试是最好的SpinLock
选择。完全没有争议。单线程 - 顺序执行。为什么SpinLock
还远远落后Monitor
?谁能给我指出一些可以证明我SpinLock
有用的代码(设备驱动程序开发除外)?
c# - 如何在 C# 中高效地为对象分配唯一 ID
我正在开发一个 C# 库,它将创建大量小对象作为正常操作的一部分(想想编译器中的 AST 节点)。我想以不会影响性能的方式为每个实例分配一个唯一标识符(在程序中是唯一的,而不是全局唯一的)。对象是不可变的,并且可以跨线程共享,因此 id 需要在线程之间是唯一的。
以下是我正在考虑的一些选项:
- 使用静态 int 或 long,并通过调用获取每个新 id
Interlocked.Increment()
- 用于
Guid.NewGuid()
生成 id - 使用带有
[ThreadStatic]
属性的静态 int 或 long 字段,然后从当前线程的ManagedThreadId
属性和线程本地计数器中的下一个值生成字符串 id。
其中一个会比其他的性能更好吗?有一个更好的方法吗?
谢谢!
编辑:
我运行了一个快速基准测试并得到以下结果:
- 0.19 秒(int 与 long 基本相同)
- 1.1 秒
- 3.5 秒
这似乎强烈指向使用Interlocked
. 但是,Interlocked
在多线程场景中是否存在减速的风险?
c# - 在 .net 中管理高/低优先级线程
场景如下:有几个低优先级线程可以被高优先级线程中断。每当高优先级线程要求低优先级线程暂停时,它们将进入Wait
状态(如果它们尚未处于等待状态)。然而,当一个高优先级线程发出低优先级线程可以Resume
的信号时,低优先级线程不应该恢复,直到所有要求低优先级线程暂停的高优先级线程都同意。
为了解决这个问题,我在计数器变量中跟踪Pause()
从高优先级线程到低优先级线程的调用。每当高优先级线程向低优先级线程请求 时Pause()
,计数器的值就会增加 1。如果在增加后计数器的值是1
,则表示线程不处于Wait
,因此要求它进入Wait
状态。否则只是增加counter
价值。相反,当高优先级线程调用时Resume()
,我们将counter
值递减,如果递减后值为0
,则表示低优先级线程Resume
现在可以。
这是我的问题的简化实现。if 语句中的比较操作Interlocked.XXX
不正确,即
if (Interlocked.Increment(ref _remain) == 1)
,因为读取/修改和比较操作不是原子的。
我在这里想念什么?我不想使用线程优先级。
c# - 如何在 C# 中的 Interlocked.Increment 之后检查溢出?
调用后检查溢出的正确方法是什么Interlocked.Increment
?
我有一个 ID 生成器,它在程序执行期间生成唯一 ID,目前我对其进行测试,增量返回零。
鉴于我每次运行生成的 ID 数量相当多,_counter
增加时可能会溢出(在异常大的输入上),我想在这种情况下抛出异常(尽早崩溃以简化调试)。
摘自微软的文档:
此方法通过包装处理溢出条件: if
location
=Int32.MaxValue
,location + 1
=Int32.MinValue
。不会抛出异常。
c# - ConcurrentQueue one element is taken by two threads
I want two threads to be working with one queue. First thread should be called every 2 seconds, and the second thread - every 3 seconds. Both threads should start at the same time. I have a problem when accessing first element of the queue. Both threads take the element with index 0. Sometimes it happens with other elements of the queue, not only with the first element. I have such an output on Console:
- Item 0 processed by 1 Time: 3:27:8
- Item 0 processed by 2 Time: 3:27:8
- Item 2 processed by 1 Time: 3:27:10
- Item 3 processed by 2 Time: 3:27:11
- Item 4 processed by 1 Time: 3:27:12
and so on..
Here is the code I use:
c# - System.Threading.Timer 的奇怪行为
我试图深入了解 Timer 将如何使用线程池。我写了以下简单的片段。
令人惊讶的是,这是我得到的输出:
使用 14 个线程。10 使用 14 个线程。18 使用 14 个线程。28 使用 14 个线程。39 使用 14 个线程。48 使用 15 个线程。58 使用 15 个线程。69 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80 使用 15 个线程。80
无论我继续运行该过程多长时间,数据变量都保持在 80。
有谁知道为什么变量在前 8 次迭代中更新并且停止递增?
c++ - 使用 c++ 替代 Windows InterlockedIncrement64
我在我的应用程序中使用 InterlockedIncrement64 进行原子增量以确保它是线程安全的,我的代码只需要基于 c 运行时库,我决定使用原子类我编写了以下 2 个方法
我认为第一种方法很好(我需要对此进行确认)!,第二种方法计算出相同的结果,但未在多线程中进行测试,但速度更快,第二种方法对我来说很可疑,我需要那些人的建议谁有经验。