一类像.NET的ConcurrentBag&LT会如何; T>实施? [英] How might a class like .NET's ConcurrentBag<T> be implemented?

查看:158
本文介绍了一类像.NET的ConcurrentBag&LT会如何; T>实施?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现自己通过的<一个存在很好奇href="http://msdn.microsoft.com/en-us/library/dd381779%28VS.100%29.aspx"><$c$c>ConcurrentBag<T>在即将到来的.NET 4.0 Framework类:

  

包是存储在订货无所谓的对象很有用,而不像套,箱包支持重复。

我的问题是:怎么可能这个想法实施?大多数集合我熟悉基本达(引擎盖下的)某种形式的阵列,其中为了不得的事情,但有的的订单(这就是为什么,尽管它不'T需要,枚举pretty的多少总是要经过一个不变的集合,无论是列表队列堆栈等,以相同的顺序)。

如果我猜的话,我可能会建议,在内部它可能是一个词典&LT; T,LinkedList的&LT; T&GT;&GT; ;但实际上似乎很可疑的考虑,将没有什么意义,只使用的任意的类型 T 作为重点。

我很期待/希望的是,这其实是一个已经被想通了的地方建立的对象类型,并有人谁知道这种类型的建立可以给我讲讲吧。这只是如此不同寻常,我 - 这些概念,很容易在现实生活中认识的,但难以转化为可用的类作为一个开发者 - 这就是为什么我很好奇,准备

修改

有些反应表明,一个可能是内部哈希表的形式。这是我最初的想法是很好,但我预见到两个问题的想法:

  1. 在哈希表是不是所有的有用,当你没有一个合适的散列code函数有问题的类型。
  2. 只需在一个集合中跟踪对象的计数是不一样的存储对象。

作为元奈特认为,也许是一个例子使这个更清楚:

 公共类ExpensiveObject(){
    私人ExpensiveObject(){
        //非常激烈的行动发生在这里
    }

    公共ExpensiveObject CreateExpensiveObject(){
        返回新ExpensiveObject();
    }
}

静态无效的主要(){
    VAR expensiveObjects =新ConcurrentBag&LT; ExpensiveObject&GT;();

    的for(int i = 0;我小于5;我++){
        expensiveObjects.Add(ExpensiveObject.CreateExpensiveObject());
    }

    //这点在code后,我要相信我有5个新
    在我的收藏//昂贵的对象

    而(expensiveObjects.Count大于0){
        ExpensiveObject expObj = NULL;
        布尔objectTaken = expensiveObjects.TryTake(出expObj);
        如果(objectTaken){
            //这里我觉得我排队一个特定的操作要
            //在5个单独的线程5个独立的对象执行,
            //但如果ConcurrentBag是一个哈希表,然后我刚刚收到
            //对象5次,所以我的工作对同一对象
            //从5个线程在同一时间!
            ThreadPool.QueueUserWorkItem(DoWorkOnExpensiveObject,expObj);
        } 其他 {
            打破;
        }
    }
}

静态无效DoWorkOnExpensiveObject(obj对象){
    ExpensiveObject expObj = OBJ为ExpensiveObject;
    如果(expObj!= NULL){
        //一些工作要做
    }
}
 

解决方案

如果你看一下细节 ConcurrentBag&LT; T&GT; ,你会发现它的,内部,基本上是一个定制的链接列表。

由于包可以包含重复,而不是通过索引访问,双向链表是一个非常好的选择执行。这使得锁是相当细粒度的插入和删除(您不必锁定整个集合,就在那里,你要插入/删除节点)。既然你不担心重复,没有散列参与。这使得一个双向链表完美。

I find myself very intrigued by the existence of a ConcurrentBag<T> class in the upcoming .NET 4.0 framework:

Bags are useful for storing objects when ordering doesn't matter, and unlike sets, bags support duplicates.

My question is: how might this idea be implemented? Most collections I'm familiar with essentially amount to (under the hood) some form of array, in which order may not "matter," but there is an order (which is why, even though it doesn't need to, enumeration will pretty much always go through an unchanged collection, be it List, Queue, Stack, etc. in the same sequence).

If I had to guess, I might suggest that internally it could be a Dictionary<T, LinkedList<T>>; but that actually seems quite dubious considering it wouldn't make sense to use just any type T as a key.

What I'm expecting/hoping is that this is actually an established object type that has already been "figured out" somewhere, and that somebody who knows of this established type can tell me about it. It's just so unusual to me--one of those concepts that's easy to understand in real life, but is difficult to translate into a usable class as a developer--which is why I'm curious as to the possibilities.

EDIT:

Some responders have suggested that a Bag could be a form of a hashtable internally. This was my initial thought as well, but I foresaw two problems with this idea:

  1. A hashtable is not all that useful when you don't have a suitable hashcode function for the type in question.
  2. Simply tracking an object's "count" in a collection is not the same as storing the object.

As Meta-Knight suggested, perhaps an example would make this more clear:

public class ExpensiveObject() {
    private ExpensiveObject() {
        // very intense operations happening in here
    }

    public ExpensiveObject CreateExpensiveObject() {
        return new ExpensiveObject();
    }
}

static void Main() {
    var expensiveObjects = new ConcurrentBag<ExpensiveObject>();

    for (int i = 0; i < 5; i++) {
        expensiveObjects.Add(ExpensiveObject.CreateExpensiveObject());
    }

    // after this point in the code, I want to believe I have 5 new
    // expensive objects in my collection

    while (expensiveObjects.Count > 0) {
        ExpensiveObject expObj = null;
        bool objectTaken = expensiveObjects.TryTake(out expObj);
        if (objectTaken) {
            // here I THINK I am queueing a particular operation to be
            // executed on 5 separate threads for 5 separate objects,
            // but if ConcurrentBag is a hashtable then I've just received
            // the object 5 times and so I am working on the same object
            // from 5 threads at the same time!
            ThreadPool.QueueUserWorkItem(DoWorkOnExpensiveObject, expObj);
        } else {
            break;
        }
    }
}

static void DoWorkOnExpensiveObject(object obj) {
    ExpensiveObject expObj = obj as ExpensiveObject;
    if (expObj != null) {
        // some work to be done
    }
}

解决方案

If you look at the details of ConcurrentBag<T>, you'll find that it's, internally, basically a customized linked list.

Since Bags can contain duplicates, and are not accessible by index, a doubly linked list is a very good option for implementation. This allows locking to be fairly fine grained for insert and removal (you don't have to lock the entire collection, just the nodes around where you're inserting/removing). Since you're not worried about duplicates, no hashing is involved. This makes a double linked list perfect.

这篇关于一类像.NET的ConcurrentBag&LT会如何; T&GT;实施?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆