2012-11-19 34 views
2

我有两个独立的任务和两个独立的操作。我认为t0是线程安全的,但我不确定t1。这是对的吗?并发字典的性能很糟糕,我需要向集合中插入大量数据。c中的并行任务和线程安全#

var t0 = new Task[2] 
{ 
    Task.Factory.StartNew(()=> 
    { 
     list1=new sortedlist<int,int>(sortedlist1) 
    } 
    }), 
    Task.Factory.StartNew(()=> 
    { 
     list2=new sortedlist<int,int>(sortedlist2) 
    }) 
}; 
Task.WaitAll(t0) 

var t1 = new Task[2] 
{ 
    Task.Factory.StartNew(()=> 
    { 
     foreach (var item in sortedlist1) 
     { 
      list1.Add(item.Key, item.Value); 
     } 
    }), 
    Task.Factory.StartNew(()=> 
    { 
     foreach (var item in sortedlist2) 
     { 
      list2.Add(item.Key, item.Value); 
     } 
    }) 
}; 
Task.WaitAll(t1) 
+0

任务之间似乎没有什么共同之处。你为什么认为它不是线程安全的? –

+0

准确地说,我很惊讶,因为在t0没有数据丢失,但在t1的一部分我的数据丢失 – mohammad

+0

这是一个http://codereview.stackexchange.com类问题 – Alex

回答

0

这看起来没问题 - 你没有在任务中访问同一个变量。 t1 []中的任务在t0 []中的任务完成之前不会运行。

您可以使用Parallel.Do()而不是在数组中创建任务,然后等待它们完成 - 这会让您的意图更加清晰,并避免大量的基于阵列的仪式。

我假设你已经组成了一个例子,而不是实际的代码?

+0

我在静态方法中编写了这段代码,它返回一个包含2个排序列表的类变量。 – mohammad

1

正如所写,此代码不起作用。第一对任务中分配的列表未分配给第二对任务使用的变量。让我们忽略它,只是看一下这里的一般概念。

这两个列表不必在单独的线程中分配以用于单独的线程。而且你绝对不需要浪费在单独任务中分配每个列表的工作。这些列表可以由主线程分配,特别是如果主线程想在任务完成后使用列表。唯一真正的问题是是否有可能同时由两个线程修改一个列表。

如果list1只能被task1读写,而list2只能被task2读写,那么你可以在它们各自的任务中做任何你想要的列表而没有任何冲突。

使用Task.WaitAll,因为您已经在等待两个任务完成。两项任务完成后,主线程可以控制list1和list2以进行进一步的修改。在一组并行执行的任务之后的一个常见后续操作是将多个任务的工作合并为最终输出。 (请参阅“MapReduce”)

+0

尽管t1中的两个操作是独立的,但在第二个任务中错过了数据 – mohammad

+0

根据这个解释,您认为多任务在这种情况下没有用处,我应该使用顺序编程。因为我想如果我使用多任务来填充列表,速度会增加 – mohammad

+0

我说多任务并不是分配列表对象所必需的。将list.add()并行执行到多个独立列表可能有价值。完成之后,您有N个任务的N个列表。那又怎么样?当你需要在列表中找到某些东西时,你是否打算执行N次查找?可能不会。常见模式是在完成所有任务后将多个任务的输出合并到一个列表中。这是“mapreduce”模式。 – dthorpe