任务并行库 (TPL) 是否处理竞争条件
Does Task Parallel Library (TPL) handle race condition
我试图了解 Task Parallel 库相对于使用传统多线程的优势,当我想到以下情况时,我一直在想它是处理竞争条件还是我们需要在代码中处理它?
这是我的代码:
int depdt = 0;
Parallel.For(1, 10, mem =>
{
for (int dep = 1; dep <= 10; dep++)
{
depdt = dep;
Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
}
Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem);
});
Console.ReadKey();
我 运行 它几次,我没有看到任何线程 interfering/overwriting "depdt" 变量。但我需要确认这一点。 (或)为了使其线程安全,我应该手动创建一个 class 的实例并像下面的代码一样实现它以避免竞争条件
int depdt = 0;
Parallel.For(1, 10, mem =>
{
Worker worker = new Worker();
worker.DoWork(mem);
});
Console.ReadKey();
public class Worker
{
public void DoWork(int mem)
{
int depdt = 0;
for (int dep = 1; dep <= 10; dep++)
{
depdt = dep;
Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
}
Console.WriteLine("Dep Value: " + depdt +" "+ "mem: "+ mem);
}
}
回复@yms:
我的意思是当使用普通线程时,变量 depdt 变得不可靠。这是我的代码:
for (int mem = 1; mem <= 10; mem++)
{
var t= new Thread(state =>
{
for (int dep = 1; dep <= 10; dep++)
{
depdt = dep;
Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
}
Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem);
});
t.Start(string.Format("Thread{0}", mem));
}
Console.ReadKey();
这是我的输出屏幕:事实上,mem 和 dep 变量都变得不可靠
没有。默认情况下,任务并行库不处理竞争条件。您需要注意同步对共享资源的访问。
如果您希望您的程序始终写入 Dep Value: 10
,那么是的,您的程序会受到可能导致打印其他值的竞争条件的影响。为了演示这个问题,只需在内部循环中引入一个延迟:
int depdt = 0;
Parallel.For(1, 10, mem =>
{
for (int dep = 1; dep <= 10; dep++)
{
depdt = dep;
Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
Thread.Sleep(mem * 100); // delay introduced here
}
Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem);
});
Console.ReadKey();
您的程序表现正确的原因是内循环执行时间非常短,可能在分配给线程的单个时间片内完成。
要避免竞争条件,您只需将 depdt
声明 移到 传递给 Parallel.For
的匿名函数中。这将导致每个线程都有自己的变量,避免冲突。
Parallel.For(1, 10, mem =>
{
int depdt = 0;
for (int dep = 1; dep <= 10; dep++)
{
depdt = dep;
Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
}
Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem);
});
我试图了解 Task Parallel 库相对于使用传统多线程的优势,当我想到以下情况时,我一直在想它是处理竞争条件还是我们需要在代码中处理它?
这是我的代码:
int depdt = 0;
Parallel.For(1, 10, mem =>
{
for (int dep = 1; dep <= 10; dep++)
{
depdt = dep;
Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
}
Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem);
});
Console.ReadKey();
我 运行 它几次,我没有看到任何线程 interfering/overwriting "depdt" 变量。但我需要确认这一点。 (或)为了使其线程安全,我应该手动创建一个 class 的实例并像下面的代码一样实现它以避免竞争条件
int depdt = 0;
Parallel.For(1, 10, mem =>
{
Worker worker = new Worker();
worker.DoWork(mem);
});
Console.ReadKey();
public class Worker
{
public void DoWork(int mem)
{
int depdt = 0;
for (int dep = 1; dep <= 10; dep++)
{
depdt = dep;
Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
}
Console.WriteLine("Dep Value: " + depdt +" "+ "mem: "+ mem);
}
}
回复@yms: 我的意思是当使用普通线程时,变量 depdt 变得不可靠。这是我的代码:
for (int mem = 1; mem <= 10; mem++)
{
var t= new Thread(state =>
{
for (int dep = 1; dep <= 10; dep++)
{
depdt = dep;
Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
}
Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem);
});
t.Start(string.Format("Thread{0}", mem));
}
Console.ReadKey();
这是我的输出屏幕:事实上,mem 和 dep 变量都变得不可靠
没有。默认情况下,任务并行库不处理竞争条件。您需要注意同步对共享资源的访问。
如果您希望您的程序始终写入 Dep Value: 10
,那么是的,您的程序会受到可能导致打印其他值的竞争条件的影响。为了演示这个问题,只需在内部循环中引入一个延迟:
int depdt = 0;
Parallel.For(1, 10, mem =>
{
for (int dep = 1; dep <= 10; dep++)
{
depdt = dep;
Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
Thread.Sleep(mem * 100); // delay introduced here
}
Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem);
});
Console.ReadKey();
您的程序表现正确的原因是内循环执行时间非常短,可能在分配给线程的单个时间片内完成。
要避免竞争条件,您只需将 depdt
声明 移到 传递给 Parallel.For
的匿名函数中。这将导致每个线程都有自己的变量,避免冲突。
Parallel.For(1, 10, mem =>
{
int depdt = 0;
for (int dep = 1; dep <= 10; dep++)
{
depdt = dep;
Console.WriteLine("MEMBER: " + mem + " " + "Dependent: " + dep);
}
Console.WriteLine("Dep Value: " + depdt + " " + "mem: " + mem);
});