執行緒安全 (Thread-safe)
現代程式設計為了提升效能,通常採用多執行緒的方式執行,但若沒有注意執行緒安全,往往會造成意想不到的錯誤。
假設現在有一個程式有 Main & Timer 兩個 Thread 都會透過 i2c command 存取硬體,模擬的程式碼如下:
執行結果如下,可以發現兩個 Thread 在做底層 i2c Read / Write 時是交錯的,
此時可利用 lock 來保護 Read / Write 的過程中是不會被其他 Thread 中斷的
執行結果如下,可以發現不再有交錯的情況了
假設現在有一個程式有 Main & Timer 兩個 Thread 都會透過 i2c command 存取硬體,模擬的程式碼如下:
using System; using System.Threading; namespace ThreadTest { class I2cGpu { public void NormalRead(int index) { Console.WriteLine("{0} ==> NormalRead{1}", Thread.CurrentThread.Name, index); Thread.Sleep(500); Console.WriteLine("{0} <== NormalRead{1}", Thread.CurrentThread.Name, index); } public void NormalWrite(int index) { Console.WriteLine("{0} ==> NormalWrite{1}", Thread.CurrentThread.Name, index); Thread.Sleep(2000); Console.WriteLine("{0} <== NormalWrite{1}", Thread.CurrentThread.Name, index); } } class ThreadTest { static void Main(string[] args) { Thread threadMain = new Thread(MainThread); threadMain.Name = "Main "; Thread threadTimer = new Thread(TimerThread); threadTimer.Name = "Timer"; threadMain.Start(); threadTimer.Start(); } private static void TimerThread() { I2cGpu i2CGpu = new I2cGpu(); for (int i = 0; i < 3; i++) { i2CGpu.NormalRead(i); i2CGpu.NormalWrite(i); } } private static void MainThread() { I2cGpu i2CGpu = new I2cGpu(); for (int i = 0; i < 3; i++) { i2CGpu.NormalRead(i); i2CGpu.NormalWrite(i); } } } }
執行結果如下,可以發現兩個 Thread 在做底層 i2c Read / Write 時是交錯的,
此時可利用 lock 來保護 Read / Write 的過程中是不會被其他 Thread 中斷的
using System; using System.Threading; namespace ThreadTest { class I2cGpu { static object locker = new object(); public void NormalRead(int index) { lock (locker) { Console.WriteLine("{0} ==> NormalRead{1}", Thread.CurrentThread.Name, index); Thread.Sleep(500); Console.WriteLine("{0} <== NormalRead{1}", Thread.CurrentThread.Name, index); } } public void NormalWrite(int index) { lock (locker) { Console.WriteLine("{0} ==> NormalWrite{1}", Thread.CurrentThread.Name, index); Thread.Sleep(2000); Console.WriteLine("{0} <== NormalWrite{1}", Thread.CurrentThread.Name, index); } } } class ThreadTest { static void Main(string[] args) { Thread threadMain = new Thread(MainThread); threadMain.Name = "Main "; Thread threadTimer = new Thread(TimerThread); threadTimer.Name = "Timer"; threadMain.Start(); threadTimer.Start(); } private static void TimerThread() { I2cGpu i2CGpu = new I2cGpu(); for (int i = 0; i < 3; i++) { i2CGpu.NormalRead(i); i2CGpu.NormalWrite(i); } } private static void MainThread() { I2cGpu i2CGpu = new I2cGpu(); for (int i = 0; i < 3; i++) { i2CGpu.NormalRead(i); i2CGpu.NormalWrite(i); } } } }
執行結果如下,可以發現不再有交錯的情況了
留言