use*_*225 1 c# multithreading .net-4.0 lockless
我试图了解Interlocked.Exchange的正确用法,所以我实现了一个带有添加和删除功能的简单排序LinkedList.
如果这不是一个线程安全列表,显然要找到插入点,你会有类似下面的内容来找到插入新节点的正确点.
public void Insert(int newValue)
{
var prev = _header;
Node curr = _header.Next;
while(curr != null && curr.value > newValue )
{
prev = curr;
curr = curr.Next;
}
var newNode = new Node(newValue, curr);
prev.Next = newNode;
}
Run Code Online (Sandbox Code Playgroud)
下面是我对如何为并发列表执行此操作的看法.是否有太多Interlocked.Exchange正在进行?如果没有这个,插入物仍然是线程安全的吗?数百或数千个互锁操作会导致性能下降吗?
public void InsertAsync(int newValue)
{
var prev = _header;
Node curr = new Node(0, null);
Interlocked.Exchange(ref curr, _header.Next);
while (curr != null && curr.value > newValue)
{
prev = Interlocked.Exchange(ref curr, curr.Next);
}
//need some locking around prev.next first, ensure not modified/deleted, etc..
//not in the scope of this question.
var newNode = new Node(newValue, prev.Next);
prev.Next = newNode;
}
Run Code Online (Sandbox Code Playgroud)
我理解,例如,curr = curr.next是一个原子读取,但我可以确定一个特定的线程将读取curr.next的最新值,而没有Interlocked?
使用Interlocked
方法可以做两件事:
Exchange
您执行相同的操作:var temp = first; first=second; return temp;
但在执行此操作时没有任何变量被另一个线程修改的风险.所以,特别是你的代码.你的第二个解决方案实际上不是线程安全 每个单独的Interlocked
操作都是原子操作,但对各种Interlocked
调用的任何数量的调用都不是原子的.鉴于你所做的一切,你的关键部分实际上要大得多; 您需要使用lock
或其他类似的机制(即信号量或监视器)来限制对单个线程的代码段的访问.在您的特定情况下,我认为整个方法是一个关键部分.如果你真的非常小心,你可以拥有几个较小的关键区块,但是很难确保不存在可能的竞争条件.
至于性能,好吧,因为代码不起作用,所以性能无关紧要.
归档时间: |
|
查看次数: |
1007 次 |
最近记录: |