线程同步打印字符串
Thread synchronization printing strings
我写了一个小程序打印 "x",然后是“+”,然后又是 "x" 等等。
想法是在两个线程中使其成为 运行,以便第一个线程打印 "x",第二个线程打印“+”。输出如下所示:
"x" -> 线程号 1
"+" -> 线程号 2
"x" -> 线程号 1enter code here
"+" -> 线程号 2
等等..
我写的似乎工作正常但在我看来它是用
很老套的方式:
public class Example
{
private static int count = 10;
private static int i = 0;
private static bool isOneActive = false;
private static void Run1(object o)
{
string s = o as string;
while(true)
{
if (!isOneActive)
{
Console.WriteLine("Hello from thread number: " +
Thread.CurrentThread.ManagedThreadId + " -> " + s);
isOneActive = true;
if (i++ > count) break;
}
}
}
private static void Run2(object o)
{
string s = o as string;
while(true)
{
if (isOneActive)
{
Console.WriteLine("Hello from thread number: " +
Thread.CurrentThread.ManagedThreadId + " -> " + s);
isOneActive = false;
if (i++ > count) break;
}
}
}
static void Main()
{
Thread t1 = new Thread(Run1);
Thread t2 = new Thread(Run2);
t1.Start("x");
t2.Start("+");
}
我知道现在 .NET 有很多用于线程同步的工具,例如 ManualResetEvent class 和任务库。那么我们如何使用 ManualResetEvent class 编写相同的程序呢?有可能吗?
您的代码不仅过时,而且效率很低。它无缘无故地旋转,除了等待什么都不做;这叫做 Busy wait 应尽可能避免。
更好的方法是使用评论中提到的 Waithandles。
对代码进行很少更改的简单实现将如下所示。
public class Example
{
private static int count = 10;
private static int i = 0;
private static AutoResetEvent firstEvent = new AutoResetEvent(true);
private static AutoResetEvent secondEvent = new AutoResetEvent(false);
private static void Run1(object o)
{
string s = o as string;
while (true)
{
firstEvent.WaitOne();
Console.WriteLine("Hello from thread number: " + Thread.CurrentThread.ManagedThreadId + " -> " + s);
secondEvent.Set();
if (Interlocked.Increment(ref i) > count)
break;
}
}
private static void Run2(object o)
{
string s = o as string;
while (true)
{
secondEvent.WaitOne();
Console.WriteLine("Hello from thread number: " + Thread.CurrentThread.ManagedThreadId + " -> " + s);
firstEvent.Set();
if (Interlocked.Increment(ref i) > count)
break;
}
}
static void Main()
{
Thread t1 = new Thread(Run1);
Thread t2 = new Thread(Run2);
t1.Start("x");
t2.Start("+");
}
}
请注意,firstEvent
是通过将 initialState 标志设置为 true
来实例化的,这意味着第一个线程最初不会等待。
考虑这个例子 (fiddle):
static void Main(string[] args)
{
var console = new object();
int i = 0;
Task.Run(() =>
{
lock (console)
while (i++ < 10)
{
Console.Write(i);
Monitor.Pulse(console);
Monitor.Wait(console);
}
});
Task.Run(() =>
{
lock (console)
while (i < 10)
{
Console.Write('+');
Monitor.Pulse(console);
Monitor.Wait(console);
}
});
Console.ReadLine(); // Task.WaitAll might be better, remove for fiddle
}
我写了一个小程序打印 "x",然后是“+”,然后又是 "x" 等等。
想法是在两个线程中使其成为 运行,以便第一个线程打印 "x",第二个线程打印“+”。输出如下所示:
"x" -> 线程号 1
"+" -> 线程号 2
"x" -> 线程号 1enter code here
"+" -> 线程号 2
等等..
我写的似乎工作正常但在我看来它是用 很老套的方式:
public class Example
{
private static int count = 10;
private static int i = 0;
private static bool isOneActive = false;
private static void Run1(object o)
{
string s = o as string;
while(true)
{
if (!isOneActive)
{
Console.WriteLine("Hello from thread number: " +
Thread.CurrentThread.ManagedThreadId + " -> " + s);
isOneActive = true;
if (i++ > count) break;
}
}
}
private static void Run2(object o)
{
string s = o as string;
while(true)
{
if (isOneActive)
{
Console.WriteLine("Hello from thread number: " +
Thread.CurrentThread.ManagedThreadId + " -> " + s);
isOneActive = false;
if (i++ > count) break;
}
}
}
static void Main()
{
Thread t1 = new Thread(Run1);
Thread t2 = new Thread(Run2);
t1.Start("x");
t2.Start("+");
}
我知道现在 .NET 有很多用于线程同步的工具,例如 ManualResetEvent class 和任务库。那么我们如何使用 ManualResetEvent class 编写相同的程序呢?有可能吗?
您的代码不仅过时,而且效率很低。它无缘无故地旋转,除了等待什么都不做;这叫做 Busy wait 应尽可能避免。
更好的方法是使用评论中提到的 Waithandles。
对代码进行很少更改的简单实现将如下所示。
public class Example
{
private static int count = 10;
private static int i = 0;
private static AutoResetEvent firstEvent = new AutoResetEvent(true);
private static AutoResetEvent secondEvent = new AutoResetEvent(false);
private static void Run1(object o)
{
string s = o as string;
while (true)
{
firstEvent.WaitOne();
Console.WriteLine("Hello from thread number: " + Thread.CurrentThread.ManagedThreadId + " -> " + s);
secondEvent.Set();
if (Interlocked.Increment(ref i) > count)
break;
}
}
private static void Run2(object o)
{
string s = o as string;
while (true)
{
secondEvent.WaitOne();
Console.WriteLine("Hello from thread number: " + Thread.CurrentThread.ManagedThreadId + " -> " + s);
firstEvent.Set();
if (Interlocked.Increment(ref i) > count)
break;
}
}
static void Main()
{
Thread t1 = new Thread(Run1);
Thread t2 = new Thread(Run2);
t1.Start("x");
t2.Start("+");
}
}
请注意,firstEvent
是通过将 initialState 标志设置为 true
来实例化的,这意味着第一个线程最初不会等待。
考虑这个例子 (fiddle):
static void Main(string[] args)
{
var console = new object();
int i = 0;
Task.Run(() =>
{
lock (console)
while (i++ < 10)
{
Console.Write(i);
Monitor.Pulse(console);
Monitor.Wait(console);
}
});
Task.Run(() =>
{
lock (console)
while (i < 10)
{
Console.Write('+');
Monitor.Pulse(console);
Monitor.Wait(console);
}
});
Console.ReadLine(); // Task.WaitAll might be better, remove for fiddle
}