C#. Multithreading
本文关键字:Multithreading | 更新日期: 2023-09-27 18:07:31
我有两个线程。第一个实现了两个方法,第二个只有一个。我需要这样同步线程:从第一个线程实现第一个方法,从第二个线程实现方法,从第一个线程实现第二个方法。我试图使用屏障,但它没有帮助:
bool complete = false;
// Start tasks
Task task_1 = factory.StartNew(() =>
{
Console.WriteLine("1");
Thread.MemoryBarrier();
if (complete)
{
Console.WriteLine("3");
}
});
Task task_2 = factory.StartNew(() =>
{
//Thread.MemoryBarrier(); // Barrier 3
Console.WriteLine("2");
Thread.MemoryBarrier(); // Barrier 1
complete = true;
Thread.MemoryBarrier();
});
task_2.Wait();
我该如何解决这个问题?
非常感谢!
谢谢你所有的帖子。我试图使用barrier
类,但结果不是我需要的。我会试着解释我的问题。我很少有调用两个或多个方法的线程:
Barrier barrier = new Barrier(2); // 2 = #threads participating.
bool complete = false;
TaskFactory factory = Task.Factory;
// Start tasks
Task task_1 = factory.StartNew(() =>
{
process_1.Server("1 and 2");
barrier.SignalAndWait(); // Wait for task 2 to catch up.
barrier.SignalAndWait(); // Wait for task 2 to print "2" and set complete = true.
if (complete)
{
process_1.Server("1 and 3");
}
});
Task task_6 = factory.StartNew(() =>
{
process_6.Server("6 and 4");
process_6.Server("6 and 3");
});
Task task_2 = factory.StartNew(() =>
{
barrier.SignalAndWait(); // Wait for task 1 to print "1".
process_2.Client("1 and 2");
complete = true;
barrier.SignalAndWait(); // Wait for task 1 to read complete as true.
process_2.Server("2 and 5");
process_2.Server("2 and 3");
});
Task task_4 = factory.StartNew(() =>
{
process_4.Client("6 and 4");
process_4.Server("4 and 7");
process_4.Server("4 and 3");
});
Task task_5 = factory.StartNew(() =>
{
process_5.Client("2 and 5");
process_5.Server("5 and 3");
});
Task task_7 = factory.StartNew(() =>
{
process_7.Client("4 and 7");
process_7.Server("7 and 3");
});
Task task_3 = factory.StartNew(() =>
{
process_3.Client("1 and 3");
process_3.Client("2 and 3");
process_3.Client("4 and 3");
process_3.Client("5 and 3");
process_3.Client("6 and 3");
process_3.Client("7 and 3");
});
task_3.Wait();
我需要确保从不同线程调用方法之间的后果,例如:process_1.Server("1 and 2");
和process_2.Client("1 and 2");
。在服务器之前调用客户端方法是不可接受的。所有依赖项:{process_1。服务器("1和2");process_2。客户端("1和2");},{process_2。服务器("2和5");process_5。Client("2 and 5");}, {process_6. 6;服务器("6和4");process_4。客户端("6和4");},{process_4。服务器("4和7");process_7。客户端("4和7");},{process_1。服务器("1和3");process_3。客户端("1和3");},{process_2。服务器("2和3");process_3。客户端("2和3");},{process_4。服务器("4和3");process_3。Client("4 and 3");}, {process_5;服务器("5和3");process_3。Client("5 and 3");}, {process_6;服务器("6和3");process_3。Client("6 and 3");}, {process_7;服务器("7和3");process_3。Client("7 and 3");}.
元素之间{…}和{…没有依赖项。因此可以执行{process_6。服务器("6和3");process_3。Client("6 and 3");}, {process_7;服务器("7和3");process_3。Client("7 and 3");},反之亦然{process_7。服务器("7和3");process_3。Client("7 and 3");}, {process_6;服务器("6和3");process_3。Client("6 and 3");}。{…是我写的。你能帮我解决这个问题吗?我想不出如何实现这个。非常感谢!
使用AutoResetEvent
AutoResetEvent waitA = new AutoResetEvent(false); //task_1 uses this to signal task_2
AutoResetEvent waitB = new AutoResetEvent(false); //task_2 uses this to signal task_1
// Start tasks
Task task_1 = Task.Run(() =>
{
Console.WriteLine("1");
waitA.Set();
waitB.WaitOne();
Console.WriteLine("3");
});
Task task_2 = Task.Run(() =>
{
waitA.WaitOne();
Console.WriteLine("2");
waitB.Set();
});
task_2.Wait();
小提琴:https://dotnetfiddle.net/rnfWRZ
语言将按本机顺序执行方法,利用这一点并重构您的代码
bool complete = false;
// Start tasks
Task task_1 = factory.StartNew(() =>
{
Console.WriteLine("1");
Console.WriteLine("2");
if (complete)
{
Console.WriteLine("3");
}
complete = true;
});
task_1.Wait();
同步攻击会混淆代码的意图。尽量避免! 假设您希望线程输出" 1,2,3 ",您可以这样做:
Barrier barrier = new Barrier(2); // 2 = #threads participating.
bool complete = false;
// Start tasks
Task task_1 = Task.Factory.StartNew(() =>
{
Console.WriteLine("1");
barrier.SignalAndWait(); // Wait for task 2 to catch up.
barrier.SignalAndWait(); // Wait for task 2 to print "2" and set complete = true.
if (complete)
{
Console.WriteLine("3");
}
});
Task task_2 = Task.Factory.StartNew(() =>
{
barrier.SignalAndWait(); // Wait for task 1 to print "1".
Console.WriteLine("2");
complete = true;
barrier.SignalAndWait(); // Wait for task 1 to read complete as true.
});
task_2.Wait();
你混淆了任务和线程,因为许多任务可以使用一些线程。来自Jon Skeet的回答
- 线程是一个较低级别的概念:如果你直接启动一个线程,你知道它将是一个单独的线程,而不是在线程池中执行。
- 任务不仅仅是"在哪里运行一些代码"的抽象-它真的只是"未来结果的承诺"。
编译器需要MemoryBarrier
来停止指令的重新排序,因为编译器可以决定做优化。
你可以做这样的事情来实现按
顺序执行class Program
{
static void Main(string[] args)
{
var task1 = new TaskFactory().StartNew(Method1);
var task2 = task1.ContinueWith(delegate { Method2(); });
var task3 = task2.ContinueWith(delegate { Method1(); });
}
private static void Method1()
{
}
private static void Method2()
{
}