[¤À¨É] C# ¤p§Þ¥©¨t¦C - Multithreading [[ ¤Jªù ]] C# ³z¹L Multithreading¡]¦h½uµ{¡^¨Ó¤ä´© parallel execution¡A thread¬O­Ó¿W¥ßªº°õ¦æ¸ô®|¡A¯à°÷¸ò¨ä¥¦thread¤@°_¶]¡C ·í¤@­ÓC#µ{¦¡¶}©l®É¡A§@·~¨t²Î©MCLR·|¦Û°Ê¬°¥¦«Ø¥ß¤@­Óthread¡A§Y main thread¡A ¨Ò¦p¡G /// using System; using System.Threading; class MainClass { static void Main() { while (true) Console.Write("M"); } } /// ³o­Ó main thread ¤£Â_Åã¥Ü "M" ¦r¤¸¡C ¡]¥i¥H«öPause¨Ó¼È°±¡A«öCtrl-C¤¤Â_¡^ ³z¹L¥Ñ main thread ¥h«Ø¥ß¤@¨Ç thread¡A´N¯à°÷Åܦ¨ multithreading¡G /// using System; using System.Threading; class MainClass { static void Main() { Thread ta = new Thread( new ThreadStart(WriteA) ); ta.Start(); Thread tb = new Thread( new ThreadStart(WriteB) ); tb.Start(); while (true) Console.Write("M"); } static void WriteA() { while (true) Console.Write("A"); } static void WriteB() { while (true) Console.Write("B"); } } /// µ²ªG¤T­Ó thread ¦b¤@°_¶]¡C ¡]µy«á¤¶²ÐThreadStart¡^ ±z¥i¥H¬°¨C­Óthread³]©wNameÄݩʡA³o¼Ë·|¤è«K°»¿ù¡A Visual Studio·|¦b Threadsµøµ¡Åã¥Ü¥¦­Ìªº Name¡G /// using System; using System.Threading; class MainClass { static void Main() { Thread ta = new Thread( new ThreadStart(Write) ); ta.Name = "A"; ta.Start(); Thread tb = new Thread( new ThreadStart(Write) ); tb.Name = "B"; tb.Start(); Thread t = Thread.CurrentThread; t.Name = "M"; Write(); } static void Write() { Thread t = Thread.CurrentThread; while (true) Console.Write( t.Name ); } } /// A, B ©M M³£·|¶]¨ì Writeªº¥DÅ餺¡A ±z¥i¥H¥Î Thread.CurrentThread ªí¥Ü·í«e¦b¶]ªº thread¡C ¨C­Óthread³£¦³¦Û¤wªº memory stack¡A³o¬O¥ÑCLR½á¤©ªº¡A ©Ò¥H¨C­Óthread³£¦³¦Û¤vªº¥»°ìÅܼơA¤£·|³Q¨ä¥¦thread¼vÅTÅܼƤº®e¡A¨Ò¦p¡G /// using System; using System.Threading; class MainClass { static void Main() { Thread ta = new Thread( new ThreadStart(Write) ); ta.Name = "A"; ta.Start(); Thread tb = new Thread( new ThreadStart(Write) ); tb.Name = "B"; tb.Start(); Thread t = Thread.CurrentThread; t.Name = "M"; Write(); } static void Write() { Thread t = Thread.CurrentThread; for (int i = 1; i <= 10; i++) { Console.Write( t.Name ); } } } /// µ²ªG¨C­Ó thread ³£Åã¥Ü 10 ­Ó¦r¤¸¡A ¦b Write ¤º¦³¥»°ìÅÜ¼Æ i ©M t¡A¨C­Óthreadªº i ©M t ³£¤£¨ü¨ä¥¦ thread¼vÅT¡C ¥»°ìÅܼƤ£·|¦@¥Î¡A¦Ó field (static ©Î instance) ´N¥i¥H¡C ¥H¤U«Ø¥ß Person Ãþ¡A¥¦¦³¤@­Ó instance field ¥s m_Married¡C §Ú­Ì­n¨D¥u¦³·í m_Married¬O false ªº®É­Ô¡A¤~¥h§â¥¦³]¦¨ true¡A §_«h¤£­n¥h³]¥¦¡C /// using System; using System.Threading; public class Person { private bool m_Married = false; public void Go() { Thread t = Thread.CurrentThread; if (! m_Married) { m_Married = true; Console.WriteLine("changed: " + t.Name); } else { Console.WriteLine("no changed: " + t.Name); } } } class MainClass { static void Main() { Person p = new Person(); Thread ta = new Thread( new ThreadStart(p.Go) ); ta.Name = "A"; ta.Start(); Thread t = Thread.CurrentThread; t.Name = "M"; p.Go(); } } /// °õ¦æµ²ªG¡G changed: M no changed: A ¦]¬°A ©M M ³£¬O³z¹L p ¨Ó©I¥s Go¡A©Ò¥H¥¦­Ì·|¦@¥Î³o­Óª«¥óªº m_Married¡A M³]¤Fm_Married¡AA¤]¥i¥HÀˬd±o¨ì¡C ·í±zÆ[¹î°õ¦æµ²ªG«á¡A·|µo²{·í¨ä¤¤¤@­Óthread §â m_Married³]¦¨ true¡A ¥t¤@­Ó´N¤£·|¦A³]¡A²Å¦X§Ú­Ìªº­n¨D¡C ¤£¹L¡A¨Æ¹ê¨Ã«D¯uªº¦p¦¹¡C ¸Õ¸Õ¦b if üÅ­z¥[¤J Thread.Sleep(1000); ¡A Åý·í«eªº thread ºÎ¯v¤@¬í¡AµM«áÄ~Äò¶]¡C if (! m_Married) { Thread.Sleep(1000); m_Married = true; Console.WriteLine("changed: " + t.Name); } else { Console.WriteLine("no changed: " + t.Name); } ·|¥X²{Ãþ¦ü³o¼Ëªºµ²ªG¡G changed: M changed: A µ²ªG M ©M A ³£·|§â m_Married ³]¦¨ true¡C °Ý¡G¬°¤°»ò¤§«eªº°õ¦æµ²ªG¨S¦³°ÝÃD©O¡H µª¡G¨S¦³µo²{°ÝÃD¡A¨Ã¤£¥Nªí¨S¦³°ÝÃD¡C ¥u¬O¡A¥¦¥i¯à¦b¤@¸U¦¸°õ¦æ¤¤¤~·|¥X²{¤@¦¸°ÝÃD¡A ¦ý¬O¡A¦pªG¨C­Ó¬P´Á·|°õ¦æ¤@¸U¦¸¡A´N¥i¥H¹w­p¨C¬P´Á·|¥X²{¤@¦¸°ÝÃD¡C ¦Ò¼{¥H¤U°õ¦æ¶¶§Ç¡A´N·|µo²{°ÝÃD­ì¦]¡G 1) m_Married = false; 2) M °õ¦æ if (! m_Married)¡A±ø¥ó¦¨¥ß 3) A °õ¦æ if (! m_Married)¡A±ø¥ó¦¨¥ß 4) M °õ¦æ m_Married = true; 5) A °õ¦æ m_Married = true; ¸Ñ¨M³o­Ó°ÝÃD¡A¨ä¤¤¤@­Ó¿ìªk¬O¥Î lock¡G public void Go() { Thread t = Thread.CurrentThread; Console.WriteLine("before enter: " + t.Name); lock (this) { Console.WriteLine("after enter: " + t.Name); if (! m_Married) { Thread.Sleep(1000); m_Married = true; Console.WriteLine("changed: " + t.Name); } else { Console.WriteLine("no changed: " + t.Name); } Console.WriteLine("before exit: " + t.Name); } Console.WriteLine("after exit: " + t.Name); } lock ªº»yªk¬O¡G lock(expression) statement_block ·í¬Y­Óthread°õ¦æ¨ìlock ³o¥y¡A´N·|¹Á¸Õ¬°ª«¥ó¨ú±omutual-exclusion lock¡A ¦pªG¨ú¨ìªº¸Ü¡A´N°õ¦æ statement_block¡A°õ¦æ«áÄÀ©ñ³o­Ó lock¡C ¦pªG¨ú¤£¨ìlock¡A´N·|µ¥«Ý¡Aª½¦Ü¨ú¨ì¬°¤î¡C ©Ò¥H¡A¥¦ªº®ÄªG¬O¥u¦³¨ú¨ìlock ªºthread¤~¯à¶i¤J statement_block ¡]¸Ó½d³ò³Q¼Ð¬°critical section¡^¡A §Y¦P®É¶¡¤£¥i¯à¦³¶W¹L¤@­Óthread¤J¨ìcritical section¡C