我在Windows 32位上用C++编写了一个低锁定列表.我在使用关键部分方面取得了很大的进步,但是我希望有人能够理智地检查我所做的事情是否正确并且我所做的事情没有任何错误:
#ifndef __LOW_LOCK_STACK_H_
#define __LOW_LOCK_STACK_H_
template< class T > class LowLockStack
{
protected:
struct Entry
{
Entry* pNext;
T* pData;
};
union Header
{
__int64 m_XChg;
struct
{
Entry* m_pNext;
__int16 m_Depth;
__int16 m_Counter;
};
};
Header m_Header;
public:
LowLockStack()
{
m_Header.m_pNext = NULL;
m_Header.m_Depth = 0;
m_Header.m_Counter = 0;
}
~LowLockStack()
{
}
void PushEntry( T* pData )
{
Entry* pEntry = new Entry;
pEntry->pData = pData;
Header header;
Header xchg;
do
{
xchg.m_XChg = m_Header.m_XChg;
header.m_pNext = …Run Code Online (Sandbox Code Playgroud) 我有一个采样的系统.我在应用程序中有多个对这些示例感兴趣的客户端线程,但是获取Sample的实际过程只能在一个上下文中进行.它足够快,它可以阻止调用过程直到采样完成,但足够慢,我不希望多个线程堆积请求.我想出了这个设计(剥离到最小的细节):
public class Sample
{
private static Sample _lastSample;
private static int _isSampling;
public static Sample TakeSample(AutomationManager automation)
{
//Only start sampling if not already sampling in some other context
if (Interlocked.CompareExchange(ref _isSampling, 0, 1) == 0)
{
try
{
Sample sample = new Sample();
sample.PerformSampling(automation);
_lastSample = sample;
}
finally
{
//We're done sampling
_isSampling = 0;
}
}
return _lastSample;
}
private void PerformSampling(AutomationManager automation)
{
//Lots of stuff going on that shouldn't be run in more than …Run Code Online (Sandbox Code Playgroud) 我试图使用互锁操作使代码片段无锁,任何想法如何翻译?
if (m_Ref == 0xFFFF)
m_Ref = 1;
else
{
if (++m_Ref == 1)
CallSomething(); //
}
Run Code Online (Sandbox Code Playgroud)
我在想类似的东西
if (InterlockedCompareExchange(&m_Ref, 1, 0xFFFF) != 0xFFFF))
{
if (InterlockedIncrement(&m_Ref) == 1)
CallSomething();
}
Run Code Online (Sandbox Code Playgroud)
这有什么问题/竞争吗?
我正在开发一个依赖 GCC 的atomic built-ins 的项目。在将项目移植到 Windows 时,我试图找到 GCC 原子的 Interlocked* 对应项。大多数操作实际上都可用,但我想念应用的操作__ATOMIC_CONSUME和__ATOMIC_ACQ_REL内存语义。由于 _*Barrier 内在函数已被弃用,Microsoft建议使用std::atomic(例如atomic_thread_fence)和类似的 C++11 标准。
我想知道:C 程序员应该做什么,我们如何在不使用 C++11 的情况下实现atomicswith__ATOMIC_CONSUME和__ATOMIC_ACQ_REL语义的可移植版本?
当在x86上运行的算法上尝试调试随机40x性能下降时,我几乎疯了,因为算法大量使用Inter64.CompareExchange和Int64.
我终于隔离了这个问题,只有当所说的Int64不是8字节对齐时才会发生.
无论我如何在StructLayout中显式定位字段,它都依赖于堆上外部对象的基地址.在x86上,基地址将是4字节对齐或8字节对齐.
我想到定义一个12字节的结构并根据对齐将Int64设置为偏移0或偏移4,但这有点像hacky.
c#中有一个很好的做法,用于在x86中对Int64执行互锁操作,以确保正确对齐吗?
编辑
代码可以在这里找到:https: //github.com/akkadotnet/akka.net/pull/1569#discussion-diff-47997213R520
它是一个基于Clr ThreadPool的线程池实现.问题是关于将自定义信号量的状态存储在8字节结构中并使用InterlockedCompareExchange64进行修改.
我有一个double[][]可能被多个线程同时修改的锯齿状数组。我想让它成为线程安全的,但如果可能的话,不要锁。线程很可能以数组中的相同元素为目标,这就是整个问题出现的原因。我找到了使用该Interlocked.CompareExchange方法原子地增加双精度值的代码:为什么没有接受双精度作为参数的 Interlocked.Add 的重载?
我的问题是:如果 中有锯齿状的数组引用,它会保持原子性Interlocked.CompareExchange吗?非常感谢您的见解。
举个例子:
public class Example
{
double[][] items;
public void AddToItem(int i, int j, double addendum)
{
double newCurrentValue = items[i][j];
double currentValue;
double newValue;
SpinWait spin = new SpinWait();
while (true) {
currentValue = newCurrentValue;
newValue = currentValue + addendum;
// This is the step of which I am uncertain:
newCurrentValue = Interlocked.CompareExchange(ref items[i][j], newValue, currentValue);
if (newCurrentValue == currentValue) break;
spin.SpinOnce();
}
}
}
Run Code Online (Sandbox Code Playgroud) 在优化程序时,我遇到了一些奇怪的性能结果,这些结果显示在以下BenchmarkDotNet基准测试中:
string _s, _y = "yo";
[Benchmark]
public void Exchange() => Interlocked.Exchange(ref _s, null);
[Benchmark]
public void CompareExchange() => Interlocked.CompareExchange(ref _s, _y, null);
Run Code Online (Sandbox Code Playgroud)
结果如下:
BenchmarkDotNet=v0.10.10, OS=Windows 10 Redstone 3 [1709, Fall Creators Update] (10.0.16299.192)
Processor=Intel Core i7-6700HQ CPU 2.60GHz (Skylake), ProcessorCount=8
Frequency=2531248 Hz, Resolution=395.0620 ns, Timer=TSC
.NET Core SDK=2.1.4
[Host] : .NET Core 2.0.5 (Framework 4.6.26020.03), 64bit RyuJIT
DefaultJob : .NET Core 2.0.5 (Framework 4.6.26020.03), 64bit RyuJIT
Method | Mean | Error | StdDev |
---------------- |----------:|----------:|----------:|
Exchange | 20.525 …Run Code Online (Sandbox Code Playgroud) 以下代码在 .NET core 3.1 中可以正常工作,但会错误地生成警告CS8625 Cannot Convert null Literals to non-nullable reference type:
#nullable enable
using System.Threading;
namespace InterlockedExchangeNullProblem {
public class Class1 {
public Class1() {
object? o = new object();
var o1 = Interlocked.Exchange(ref o, null); // ok
class2? c = new class2();
var c1 = Interlocked.Exchange(ref c, null); // error CS8625 Cannot convert null literal to non-nullable reference type.
}
}
public class class2{}
}
Run Code Online (Sandbox Code Playgroud)
如果它适用于object?,它也应该适用于class2?。
这段代码是线程安全的吗?或者这样说:
无论如何调用GetIt()并且GetIt()将返回相同的数字到2个不同的线程
Private Shared hitCount As Long = 1
Public Shared Function GetIt() As Long
Threading.Interlocked.Increment(hitCount)
DoSomethingQuick(hitCount)
Return hitCount
End Function
Run Code Online (Sandbox Code Playgroud)
看起来这是可能的,那么我应该Interlocked.Read()在一个区块中使用或锁定整个东西吗?
的文档Interlocked.Exchange<T>包含以下注释:
此方法重载优于
Exchange(Object, Object)方法重载,因为后者需要对目标对象的后期绑定访问。
这张纸条使我很困惑。对我来说,“后期绑定”是指虚拟方法的分派,似乎与原子交换两个内存位置的技术细节没有任何关系。笔记在说什么呢?在这种情况下,“后期访问”是什么意思?
interlocked ×10
c# ×6
.net ×3
c++ ×2
concurrency ×2
.net-5 ×1
.net-core ×1
arrays ×1
atomic ×1
c ×1
gcc ×1
late-binding ×1
locking ×1
performance ×1
stack ×1
winapi ×1
windows ×1
x86 ×1