有趣的多线程编程(3)——线程内部是如何进行的?
原创
©著作权归作者所有:来自51CTO博客作者山可可的原创作品,请联系作者获取转载授权,否则将追究法律责任
看一下以下两个例子的运行结果:
//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=1Incremented tmp to 1Written count=1 Read count=1 Incremented tmp to 2Read count=1 Written count=2 Read count=2Incremented tmp to 2 Incremented tmp to 3Written count=2 Written count=3Read count=3 Read count=3Incremented tmp to 4 Incremented tmp to 4 Written count=4Written count=4 Read count=4Read count=4 Incremented tmp to 5 Written count=5Incremented tmp to 5Written count=5Read count=5Incremented tmp to 6Written count=6Final 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=0Incremented tmp to 1Written count=1 Read count=1 Incremented tmp to 2 Written count=2Read count=2Incremented tmp to 3Written count=3 Read count=3 Incremented tmp to 4 Written count=4Read count=4Incremented tmp to 5Written count=5 Read count=5 Incremented tmp to 6 Written count=6Read count=6Incremented tmp to 7Written count=7 Read count=7 Incremented tmp to 8 Written count=8Read count=8Incremented tmp to 9Written count=9 Read count=9 Incremented tmp to 10 Written count=10Final 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比较一下,再想想看。