3 回答

TA贡献1864条经验 获得超2个赞
如果您的应用程序并发(并行性是并发类型之一)并且您想使用线程安全的集合,则没有理由自己锁定集合。微软提供了一堆并发集合,它们存在于 System.Collections.Concurrent Thread-safe Collections

TA贡献1829条经验 获得超6个赞
Parallel.ForEach是一种尝试在代码中获得更多并行性的方法。lock倾向于降低代码中的并行性1。因此,想要将它们结合起来很少是正确的2。
正如Olegl 所建议的那样,并发集合可能是避免lock.
另一种有趣的方法是在这里使用PLINQ而不是Parallel.ForEach. 已经是 2019 年了,再写一个循环有什么好玩的?
这会做这样的事情:
secondList.AddRange(list.AsParallel.Where(item =>
{
//consider other processes works in here
return item.Active;
});
这使您可以保留非线程安全的secondList集合,但仍然不必担心锁——因为AddRange最终消耗IEnumerable<T>PLINQ 提供的是您自己现有的线程调用;所以只有一个线程将项目添加到集合中。
PLINQ 尝试调整缓冲选项,但可能无法完成足够好的工作,具体取决于输入的大小list和它选择使用的线程数。如果您对它的任何加速不满意(或者它没有实现任何加速),请WithXxx在注销之前尝试使用它提供的方法。
如果我必须在您的两个示例之间进行选择(假设它们在其他方面都是正确的),我会选择选项 2,因为它在持有所有其他工人激烈争夺的锁时工作较少。
1除非您知道将请求的所有锁都足够细粒度,以至于没有两个并行线程会尝试获取相同的锁。但如果我们知道这一点,我们为什么还要使用锁呢?
2所以我会说,当所有并行锁都在同一个锁对象上时,将它们组合起来“总是”不正确,除非在lock.

TA贡献1835条经验 获得超7个赞
例如那种用途:
public static T CastTo<T>(this ArrayOfKeyValueOfstringstringKeyValueOfstringstring[] item)
{
var obj = Activator.CreateInstance(typeof(T), true);
var padlock = new object();
Parallel.ForEach(typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public), prop =>
{
lock (padlock)
{
if (!prop.TryGetAttribute<GldnhrnFieldAttribute>(out var fieldAttribute))
return;
var code = fieldAttribute?.Code;
if (string.IsNullOrEmpty(code)) return;
SetPropertyValue(item, obj, prop);
}
});
return (T)obj;
}
如您所见,我想在这里将我的数据转换为类。不同代码块的相同问题,我应该锁定所有代码块还是应该只在调用 SetPropertyValue 方法之前锁定?
public static T CastTo<T>(this ArrayOfKeyValueOfstringstringKeyValueOfstringstring[] item)
{
var obj = Activator.CreateInstance(typeof(T), true);
var padlock = new object();
Parallel.ForEach(typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public), prop =>
{
if (!prop.TryGetAttribute<GldnhrnFieldAttribute>(out var fieldAttribute))
return;
var code = fieldAttribute?.Code;
if (string.IsNullOrEmpty(code)) return;
lock (padlock)
SetPropertyValue(item, obj, prop);
});
return (T)obj;
}
- 3 回答
- 0 关注
- 302 浏览
添加回答
举报