看一下以下两个例子的运行结果:
//TestThread.cs
using System;
using System.Threading;
public class Test
{
static int count=0;
static void Main()
{
ThreadStart job = new ThreadStart(ThreadJob);
Thread thread = new Thread(job);
thread.Start();
for (int i=0; i < 5; i++)
{
count++;
}
thread.Join();
Console.WriteLine ("Final count: {0}", count);
}
static void ThreadJob()
{
for (int i=0; i < 5; i++)
{
count++;
}
}
}
//InnerDataThread.cs
using System;
using System.Threading;
public class Test
{
static int count=0;
static void Main()
{
ThreadStart job = new ThreadStart(ThreadJob);
Thread thread = new Thread(job);
thread.Start();
for (int i=0; i < 5; i++)
{
int tmp = count;
Console.WriteLine ("Read count={0}", tmp);
Thread.Sleep(50);
tmp++;
Console.WriteLine ("Incremented tmp to {0}", tmp);
Thread.Sleep(20);
count = tmp;
Console.WriteLine ("Written count={0}", tmp);
Thread.Sleep(30);
}
thread.Join();
Console.WriteLine ("Final count: {0}", count);
}
static void ThreadJob()
{
for (int i=0; i < 5; i++)
{
int tmp = count;
Console.WriteLine ("\t\t\t\tRead count={0}", tmp);
Thread.Sleep(20);
tmp++;
Console.WriteLine ("\t\t\t\tIncremented tmp to {0}", tmp);
Thread.Sleep(10);
count = tmp;
Console.WriteLine ("\t\t\t\tWritten count={0}", tmp);
Thread.Sleep(40);
}
}
}
Read count=0
Read count=0
Incremented tmp to 1
Written count=1
Incremented tmp to 1
Written count=1
Read count=1
Incremented tmp to 2
Read count=1
Written count=2
Read count=2
Incremented tmp to 2
Incremented tmp to 3
Written count=2
Written count=3
Read count=3
Read count=3
Incremented tmp to 4
Incremented tmp to 4
Written count=4
Written count=4
Read count=4
Read count=4
Incremented tmp to 5
Written count=5
Incremented tmp to 5
Written count=5
Read count=5
Incremented tmp to 6
Written count=6
Final count: 6
再比较下面这个例子:
//使用Monitor.Enter/Exit
//MonitorThread.cs
using System;
using System.Threading;
public class Test
{
static int count=0;
static readonly object countLock = new object();
static void Main()
{
ThreadStart job = new ThreadStart(ThreadJob);
Thread thread = new Thread(job);
thread.Start();
for (int i=0; i < 5; i++)
{
Monitor.Enter(countLock);
int tmp = count;
Console.WriteLine ("Read count={0}", tmp);
Thread.Sleep(50);
tmp++;
Console.WriteLine ("Incremented tmp to {0}", tmp);
Thread.Sleep(20);
count = tmp;
Console.WriteLine ("Written count={0}", tmp);
Monitor.Exit(countLock);
Thread.Sleep(30);
}
thread.Join();
Console.WriteLine ("Final count: {0}", count);
}
static void ThreadJob()
{
for (int i=0; i < 5; i++)
{
Monitor.Enter(countLock);
int tmp = count;
Console.WriteLine ("\t\t\t\tRead count={0}", tmp);
Thread.Sleep(20);
tmp++;
Console.WriteLine ("\t\t\t\tIncremented tmp to {0}", tmp);
Thread.Sleep(10);
count = tmp;
Console.WriteLine ("\t\t\t\tWritten count={0}", tmp);
Monitor.Exit(countLock);
Thread.Sleep(40);
}
}
}
结果与上例InnerDataThread.cs是不一样的,原因就在于Monitor的使用了。
Read count=0
Incremented tmp to 1
Written count=1
Read count=1
Incremented tmp to 2
Written count=2
Read count=2
Incremented tmp to 3
Written count=3
Read count=3
Incremented tmp to 4
Written count=4
Read count=4
Incremented tmp to 5
Written count=5
Read count=5
Incremented tmp to 6
Written count=6
Read count=6
Incremented tmp to 7
Written count=7
Read count=7
Incremented tmp to 8
Written count=8
Read count=8
Incremented tmp to 9
Written count=9
Read count=9
Incremented tmp to 10
Written count=10
Final count: 10
下面使用lock来锁定线程:
// LockThread.cs
using System;
using System.Threading;
public class Test
{
static int count=0;
static readonly object countLock = new object();
static void Main()
{
ThreadStart job = new ThreadStart(ThreadJob);
Thread thread = new Thread(job);
thread.Start();
for (int i=0; i < 5; i++)
{
lock (countLock)
{
int tmp = count;
Console.WriteLine ("Read count={0}", tmp);
Thread.Sleep(50);
tmp++;
Console.WriteLine ("Incremented tmp to {0}", tmp);
Thread.Sleep(20);
count = tmp;
Console.WriteLine ("Written count={0}", tmp);
}
Thread.Sleep(30);
}
thread.Join();
Console.WriteLine ("Final count: {0}", count);
}
static void ThreadJob()
{
for (int i=0; i < 5; i++)
{
lock (countLock)
{
int tmp = count;
Console.WriteLine ("\t\t\t\tRead count={0}", tmp);
Thread.Sleep(20);
tmp++;
Console.WriteLine ("\t\t\t\tIncremented tmp to {0}", tmp);
if (count < 100)
throw new Exception();
Thread.Sleep(10);
count = tmp;
Console.WriteLine ("\t\t\t\tWritten count={0}", tmp);
}
Thread.Sleep(40);
}
}
}
结果如何?与MonitorThread.cs比较一下,再想想看。