gpt4 book ai didi

.net - 非并发集合在并发集合中安全吗?

转载 作者:行者123 更新时间:2023-12-02 18:48:23 26 4
gpt4 key购买 nike

我希望开始在我正在进行的项目中实现一些并发功能。我最近发现了我打算利用的 System.Collections.Concurrent 命名空间。

我用来跟踪操作整体状态的对象本质上是一个包含一些嵌套自定义对象的字典。我的想法是,只要最高级别的集合配置为并发/线程安全,那么嵌套集合是否是并发/线程安全并不重要,因为数据将被更高级别的集合锁定。

这是正确的假设吗?

例如,像下面这样的 PowerShell 中的某些东西可以安全使用吗?

[System.Collections.Concurrent.ConcurrentDictionary[[String], [MyCustomClass]]]::new()

此外,我还有一些扩展 HashSet 以避免重复的自定义类。由于 System.Collections。 Concurrent 没有 HashSet 类,获得类似功能但并发的推荐方法是什么?

最佳答案

My thought is that as long as the highest level collection is configured to be concurrent/thread safe, it doesn't matter if the nested collections are, since the data will be locked by the higher level collection.

Is this the correct assumption?

不,这不是一个安全的假设。

假设您创建了一个包含一堆常规哈希表的并发字典:

using namespace System.Collections.Concurrent

# Create thread-safe dictionary
$rootDict = [ConcurrentDictionary[string,hashtable]]::new()
  • $rootDict现在是线程安全的 - 多个线程不能同时修改 'A'通过覆盖对哈希表的引用来输入
  • 我们添加到 $rootDict 的任何内部哈希表不是线程安全的——它仍然只是一个普通的哈希表

在 PowerShell 7 中,使用 ForEach-Object -Parallel 时可以观察到这一点对这样的数据结构进行操作:

using namespace System.Collections.Concurrent

# Create thread-safe dictionary
$rootDict = [ConcurrentDictionary[string,hashtable]]::new()

1..100 |ForEach-Object -Parallel {
# We need a reference to our safe top-level dictionary
$dict = $using:rootDict

# ... and we need a key
$rootKey = $_ % 2 -eq 0 ? 'even' : 'odd'

# Thread-safe acquisition of inner hashtable
$innerDict = $dict.GetOrAdd($rootKey, {param($key) return @{}})

# Add a bit of jitter for realism
Start-Sleep -Milliseconds (Get-Random -Minimum 50 -Maximum 250)

# Update inner hashtable entry
$innerDict['Counter'] += 1
} -ThrottleLimit 10

# Are these really the results we're expecting...?
$rootDict['odd','even']

如果内部哈希表条目是线程安全的并发更新,你会期望两个计数器都在 50 ,但我在笔记本电脑上得到的结果是这样的:

Name                           Value
---- -----
Counter 46
Counter 43

我们可以看到内部“计数器”条目的多个更新在此过程中丢失,可能是由于并发更新所致。


为了检验这个假设,让我们做同样的实验,但使用另一种并发字典类型而不是哈希表:

using namespace System.Collections.Concurrent

# Create thread-safe dictionary with a thread-safe item type
$rootDict = [ConcurrentDictionary[string,ConcurrentDictionary[string,int]]]::new()

1..100 |ForEach-Object -Parallel {
# We need a reference to our safe top-level dictionary
$dict = $using:rootDict

# ... and we need a key
$rootKey = $_ % 2 -eq 0 ? 'even' : 'odd'

# Thread-safe acquisition of inner hashtable
$innerDict = $dict.GetOrAdd($rootKey, {param($key) return @{}})

# Add a bit of jitter for realism
Start-Sleep -Milliseconds (Get-Random -Minimum 50 -Maximum 250)

# Thread-safe update of inner dictionary
[void]$innerDict.AddOrUpdate('Counter', {param($key) return 1}, {param($key,$value) return $value + 1})
} -ThrottleLimit 10

# These should be the exact results we're expecting!
$rootDict['odd','even']

现在我得到:

Key     Value
--- -----
Counter 50
Counter 50

I have some custom class that extend HashSet to avoid duplicates. Since System.Collections. Concurrent don't have a HashSet class, what is the recommended way to get similar functionality but concurrently?

而不是显式继承自 HashSet ,我强烈建议包装 HashSet然后用 ReaderWriterLockSlim 保护所有你想公开给用户的方法- 这样您就可以在不牺牲读取访问性能的情况下实现线程安全。

在这里,反对使用[int]作为示例日期类型:

using namespace System.Collections.Generic
using namespace System.Threading

class ConcurrentSet
{
hidden [ReaderWriterLockSlim]
$_lock

hidden [HashSet[int]]
$_set

ConcurrentSet()
{
$this._set = [HashSet[int]]::new()
$this._lock = [System.Threading.ReaderWriterLockSlim]::new()
}

[bool]
Add([int]$item)
{
# Any method that modifies the set should be guarded
# by a WriteLock - guaranteeing exclusive update access
$this._lock.EnterWriteLock()
try{
return $this._set.Add($item)
}
finally{
$this._lock.ExitWriteLock()
}
}

[bool]
IsSubsetOf([IEnumerable[int]]$other)
{
# For the read-only methods a read-lock will suffice
$this._lock.EnterReadLock()
try{
return $this._set.IsSubsetOf($other)
}
finally{
$this._lock.ExitReadLock()
}
}

# Repeat appropriate lock pattern for all [HashSet] methods you want to expose
}

您可以通过 wrapping a HashSet<object> 使包装器更加灵活并使用 custom comparer 控制行为

关于.net - 非并发集合在并发集合中安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67114770/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com