在 .NET 中同步读写集合

发布于 2024-09-18 12:34:54 字数 1771 浏览 3 评论 0原文

我有一个包含项目集合的对象。我希望能够通过 AddItem 方法将项目添加到集合中,并浏览集合中的所有项目。我的对象必须是线程安全的。我正在使用 ReaderWriterLockSlim 来确保正确的同步。 我应该如何同步 GoThroughAllItems 方法?我应该在整个持续时间内启动一个大的 ReadLock(这可能会很长),还是应该释放从集合中获取的每一项的锁,并为下一项重新获取锁?

这是一些示例代码:

private ReaderWriterLockSlim @lock = new ReaderWriterLockSlim();
private List items = new List();

public void AddItem(Item item)
{
    [email protected]();

    try
    {
        //do something with item and add it to the collection
        this.items.Add(item);
    }
    finally
    {
        [email protected]();
    }
}

public void GoThroughAllItems()
{
    [email protected]();

    try
    {
        foreach (Item item in this.Items)
        {
#if option2
            [email protected]();
#endif

            //process item, which may take a long time

#if option2
            [email protected]();
#endif
        }
    }

#if option2
    catch
#endif
#if option1
    finally
#endif
    {
        [email protected]();
    }
}

I have an object which holds a collection of items. I want to be able to add items to the collection through an AddItem method and also to go through all of the items in the collection. My object must be thread safe. I am using a ReaderWriterLockSlim to assure proper synchronization.
How should I synchronize the GoThroughAllItems method? Should I just start a big ReadLock throughout its entire duration, which may be very long, or should I release the lock for each item fetched from the collection, and re-acquire the lock again for the next one?

Here is some sample code:

private ReaderWriterLockSlim @lock = new ReaderWriterLockSlim();
private List items = new List();

public void AddItem(Item item)
{
    [email protected]();

    try
    {
        //do something with item and add it to the collection
        this.items.Add(item);
    }
    finally
    {
        [email protected]();
    }
}

public void GoThroughAllItems()
{
    [email protected]();

    try
    {
        foreach (Item item in this.Items)
        {
#if option2
            [email protected]();
#endif

            //process item, which may take a long time

#if option2
            [email protected]();
#endif
        }
    }

#if option2
    catch
#endif
#if option1
    finally
#endif
    {
        [email protected]();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光沙漏 2024-09-25 12:34:54

这里最好的方法是创建集合的副本,然后对其进行迭代。它有很大的内存开销(但很快就会被释放)。

伪代码:

read lock
   foreach oldColl
      populate newColl
exit lock

   foreach newColl
      do things

并且您对每个项目加锁的代码将不起作用,因为其他线程可能会修改集合并会导致错误,因为 foreach 不允许修改集合。

The best way here is to create a copy of collection, then iterate over it. It has significant memory overhead (but it will be released soon after).

Pseudo code:

read lock
   foreach oldColl
      populate newColl
exit lock

   foreach newColl
      do things

and you code with locks per item will not work, because other thread might modify collection and it will cause error, because foreach doesn't allow modification of collections.

挖鼻大婶 2024-09-25 12:34:54

我会简单地选择第一个选项,即 foreach 周围的读取区域,因为读取块中允许多个线程,因此速度相当慢并不重要。另一方面,独占写入操作相当快。所以这应该是一个很好的解决方案。

I would simply choose your first option with the read region around the foreach since multiple threads are allowed in the read block it does not matter that it is rather slow. The exclusive write operation on the other hand is quite fast. So that should be a good solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文