多執行緒共用變數時,會發生意料外的錯誤。
參考這篇[多個 Thread 共用變數]
http://www.ez2o.com/Blog/Post/csharp-Mulit-Thread-Lock-Variable
在多個執行緒共用變數時,因為該變數同時給多個執行緒使用,
使得可能同時有多個執行緒改同一個變數,
讓變數的行為不如預期。
原程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ThreadSumTest
{
class Program
{
static int threadCount = 0;
static void HelloThread(Object time)
{
Console.WriteLine("--START--Now{0},Thread{1}", ((DateTime) time).ToShortTimeString() , Thread.CurrentThread.ManagedThreadId);
Random ran = new Random();
Thread.Sleep(ran.Next(0,1000));
Console.WriteLine("--E N D--Now{0},Thread{1}", ((DateTime)time).ToShortTimeString(), Thread.CurrentThread.ManagedThreadId);
for (int i = 0; i < 10000; i++)
{
threadCount++;
}
}
static void Main(string[] args)
{
List<Thread> ThreadList=new List<Thread>();
for (int i = 0; i < 10; i++)
{
ThreadList.Add(new Thread(new ParameterizedThreadStart(HelloThread)));
ThreadList[i].Start(DateTime.Now);
}
foreach (Thread requestThread in ThreadList)
{
requestThread.Join();
}
Console.WriteLine(threadCount);
}
}
}
錯誤結果

錯誤行為不是每次都會發生,但是一定會發生,所以一定要處理。
簡單的方式就是用lock語法把共用變數的區段包起來,
透過新增一個物件來當作辨認的鑰匙,來確保該程式區段每一次都只有一個執行緒才處理。
但此方式會讓多執行緒在某一區段變成單執行緒,故lock的區段不可太長,不然就失去多執行緒的意義了。
修改後程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ThreadSumTest
{
class Program
{
static int threadCount = 0;
static object countLock=new object();
static void HelloThread(Object time)
{
Console.WriteLine("--START--Now{0},Thread{1}", ((DateTime) time).ToShortTimeString() , Thread.CurrentThread.ManagedThreadId);
Random ran = new Random();
Thread.Sleep(ran.Next(0,1000));
Console.WriteLine("--E N D--Now{0},Thread{1}", ((DateTime)time).ToShortTimeString(), Thread.CurrentThread.ManagedThreadId);
lock (countLock)
{
for (int i = 0; i < 10000; i++)
{
threadCount++;
}
}
}
static void Main(string[] args)
{
List<Thread> ThreadList=new List<Thread>();
for (int i = 0; i < 10; i++)
{
ThreadList.Add(new Thread(new ParameterizedThreadStart(HelloThread)));
ThreadList[i].Start(DateTime.Now);
}
foreach (Thread requestThread in ThreadList)
{
requestThread.Join();
}
Console.WriteLine(threadCount);
}
}
}
另跟多執行緒有關之文章
[執行緒的順序啟動 - Thread.Join方法]
https://dotblogs.com.tw/yc421206/2011/01/04/20575