并行会导致死锁吗?

时间:2014-01-24 23:18:15

标签: c# multithreading parallel-processing

我是C#的新手,但是学习它。我发现C#有很多很棒的方法,比如Parallel。

所以,假设我的程序有这种方法。

private void stackOverFlowExample()
{
    List<string> testCompany = new List<string>();
    List<People> testList = new List<People>();

    testCompany.Add("Stack Over Flow 1");
    testCompany.Add("Stack Over Flow 2");
    testCompany.Add("Stack Over Flow 3");
    ...(1000 Times)...

    Parallel.ForEach(testCompany, company => 
    {
        testList.Add(new People()
        {
            Name = value1, // Some values
            Address = value2,
            Phone = value3,
            Company = company
        });
    });
}

上面的代码是否存在与线程相关的问题?是否有任何与线程问题解决相关的书籍或指南可以推荐?

3 个答案:

答案 0 :(得分:2)

该代码确实存在与线程相关的问题,但不会被称为死锁。

代码的问题是多个线程会将项添加到列表中,但List<T>类不是线程安全的,所以如果任何线程同时添加项目,列表对象将是损坏。

由于您未在代码中使用任何同步锁,因此不会出现死锁。当线程锁定两个不同的东西时会发生死锁,因此即使您在代码中添加了锁定以使其保证线程安全,也可能没有死锁,因为您只能锁定一个东西。

有关死锁的简单解释:How to explain the "deadlock" better?


代码的线程安全版本会使用锁定代码将项目添加到列表中,以确保一次只有一个线程输入该代码:

private void stackOverFlowExample()
{
    List<string> testCompany = new List<string>();
    List<People> testList = new List<People>();
    object sync = new Object();

    testCompany.Add("Stack Over Flow 1");
    testCompany.Add("Stack Over Flow 2");
    testCompany.Add("Stack Over Flow 3");
    ...(1000 Times)...

    Parallel.ForEach(testCompany, company => 
    {
        People p = new People()
        {
            Name = value1, // Some values
            Address = value2,
            Phone = value3,
            Company = company
        };
        lock (sync) {
          testList.Add(p);
        }
    });
}

答案 1 :(得分:1)

不,要获得死锁,您至少需要两个共享资源来锁定。但如果您的意思是线程安全的代码,那么可能是的,因为您在没有任何线程控制的情况下访问testList ...

对于僵局,你必须有这样的东西

>Thread1
lock(a)
   lock(b)
     DoSomething1()


>Thread2
lock(b)
   lock(a)
     DoSomething2()  

答案 2 :(得分:0)

不,死锁与锁定相关联,而不是直接与并行编程相关联。因此,代码中可能存在死锁,但它与使用Parallel.ForEach的事实并不直接相关。

死锁示例:

        object locker1 = new object(); 
        object locker2 = new object(); 

        new Thread (() => { 
                lock (locker1) 
                { 
                    Thread.Sleep (1000); 
                    lock (locker2); // Deadlock 
                } 
            }).Start(); 

        lock (locker2) 
        { 
            Thread.Sleep (1000); 
            lock (locker1); // Deadlock 
        } 

我建议您阅读我最新的博客文章,了解构建多线程应用程序时最常见的错误和陷阱。 : http://blog.goyello.com/2014/01/21/threading-in-c-7-things-you-should-always-remember-about/

如果您想了解更多有关C#中的线程的信息,我建议您阅读这本免费电子书: http://www.albahari.info/threading/threading.pdf