PLINQ问题/技术要插入多线程,无锁的列表(在C#中)[英] PLINQ problem / techniques to impliment multi-threaded, lock-free lists (in C#)

本文是小编为大家收集整理的关于PLINQ问题/技术要插入多线程,无锁的列表(在C#中)的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

这是所讨论的代码:

             parentNodes.AsParallel().ForAll(parent =>
            {
                List<Piece> plist = parent.Field.GetValidOrientations(pieceQueue[parent.Level]);

                plist.ForEach(p =>
                {
                    TreeNode child = new TreeNode(p, parent);
                    var score = child.CalculateScore(root);
                    levelNodes.Add(child);
                });

            });

在运行时,该代码偶尔将null引用留在LevelNodes中.我怀疑这是由于线程锁定的,因为如果正常(非平行)foreach被称为Forall.

带有plinq强度,'levelNodes.add(child);'偶尔还会带有消息:"源数组不够长.

有任何消除此问题的建议吗?
也许通过无锁的列表强度会提高性能? (一个人如何处理?)

推荐答案

您真的需要这两个级别的并行性吗?仅在父节点上并行并行吗?

无论如何,如果绝对不是一个好主意,则从多个线程中写入List<T>.但是,PFX带有一个并发收藏,可能满足您的需求: ConcurrentBag ConcurrentBag ConcurrentBag/a>.它是无序的(允许它是无锁的),但是考虑到这里的线程之间的相互作用,我想这不是您的问题.

本文地址:https://www.itbaoku.cn/post/1557202.html

问题描述

Here's the code in question:

             parentNodes.AsParallel().ForAll(parent =>
            {
                List<Piece> plist = parent.Field.GetValidOrientations(pieceQueue[parent.Level]);

                plist.ForEach(p =>
                {
                    TreeNode child = new TreeNode(p, parent);
                    var score = child.CalculateScore(root);
                    levelNodes.Add(child);
                });

            });

On runtime, that code occasionally leaves null references in levelNodes. I suspect this is due to thread lock, because the problem disappears if a normal (non-parallel) ForEach is called in place of the ForAll.

With the PLINQ implimentation, 'levelNodes.Add(child);' also occasionally throws an IndexOutOfRangeException with the message: "Source array was not long enough. Check srcIndex and length, and the array's lower bounds."

Any suggestions to eliminate this problem?
Or perhaps performance would be increased with a lock-free List implimentation? (How might one go about this?)

推荐答案

Do you really need both levels of parallelism here? Is it not enough to just parallelise over the parent nodes?

Anyway, writing to a List<T> from multiple threads without locking if definitely not a good idea. However, PFX comes with a concurrent collection which may fit your needs: ConcurrentBag. It's unordered (to allow it to be lock-free) but given the interplay between threads here, I guess that's not an issue for you.