我是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
});
});
}
上面的代码是否存在与线程相关的问题?是否有任何与线程问题解决相关的书籍或指南可以推荐?
答案 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