通过多线程,c#能够并行执行代码。每一个线程都有它独立的执行路径,所有的线程都能够访问共有的变量。下面的例子说明这个问题:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Threading;
using System.Threading.Tasks;
namespace ThresdScript
{
class MainClass
{
static string str = "";
static void Main(string[] args)
{
Thread t1 = new Thread(Add1);
t1.Start();
Thread t2 = new Thread(Add2);
t2.Start();
//等待一段时间
Thread.Sleep(1000);
Console.WriteLine( str );
Console.ReadKey();
}
//线程1
public static void Add1()
{
for (int i = 0; i < 20; i++)
{
Thread.Sleep(10);
str += 'a';
}
}
//线程2
public static void Add2()
{
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
Thread.Sleep(10);
str += 'b';
}
}
}
}
}
由于两个线程并行执行,字符串str时而被Add1操作,时而被Add2操作,所以打印如下结果:
线程互斥.png
为了避免线程竞争,可以通过加锁的方式(Lock)来处理,当2个线程争夺一个锁的时候,只能有一个线程有资格获取,另一个挂起等待。一直等到可用为止,这种情况,保证在同一时刻只有一个线程能进入临界区。程序改为下面的状态:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Threading;
using System.Threading.Tasks;
namespace ThresdScript
{
class MainClass
{
static string str = "";
static void Main(string[] args)
{
Thread t1 = new Thread(Add1);
t1.Start();
Thread t2 = new Thread(Add2);
t2.Start();
//等待一段时间
Thread.Sleep(1000);
Console.WriteLine( str );
Console.ReadKey();
}
//线程1
public static void Add1()
{
lock (str)
{
for (int i = 0; i < 20; i++)
{
Thread.Sleep(10);
str += 'a';
}
}
}
//线程2
public static void Add2()
{
lock (str)
{
for (int i = 0; i < 20; i++)
{
Thread.Sleep(10);
str += 'b';
}
}
}
}
}
运行后的2种情况:
第一种.png
第二种.png
正文完