今天晚上睡不着,翻来覆去,索性就不睡了,起来把C#的多线程学一下。
什么是线程?
线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但是代码区是共享的,不同的线程可以执行相同的函数。
C#中与线程相关的一点东西:Thread类,封装了线程相关的一系列操作;System.Threading,要用到的命名空间
简单线程的创建
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace testing { class Program { public static void Print() { Console.WriteLine("新线程"); } static void Main(string[] args) { Thread mThread = new Thread(new ThreadStart(Print)); mThread.Name = "子线程"; mThread.Start(); Console.WriteLine(mThread.Name); Console.ReadKey(); } } }
实例化Thread的时候需要用到一个ThreadStart类型的委托,也就是新线程的处理函数。
线程处理的几个重要方法:
start(),启动线程 sleep(int),静态方法,暂停当前线程指定时间 abort(),用于终止一个线程 suspend(),挂起线程 resume(),恢复被挂起的线程
(未完待续)
关于Join方法,用来阻塞方法调用时的当前线程,等待指定线程执行完毕,再恢复当前线程的执行。
示例代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ThreadLearn { class Program { public static void Print() { for (int i = 0; i < 10; i++) { Console.WriteLine(Thread.CurrentThread.Name + " i=" + i); } } static void Main(string[] args) { Thread.CurrentThread.Name = "主线程"; Thread newThread = new Thread(new ThreadStart(Print)); newThread.Name = "新线程"; for (int j = 0; j < 20; j++) { if (j == 10) { newThread.Start(); newThread.Join(); } else { Console.WriteLine(Thread.CurrentThread.Name + " j=" + j); } } Console.ReadLine(); //i.ToString(); } } }
Thread.ThreadState属性
此属性代表了线程的不同状态,取值如下:
Aborted:线程已停止;
AbortRequested:线程的Thread.Abort()方法已被调用,但是线程还未停止;
Background:线程在后台执行,与属性Thread.IsBackground有关;后台线程不影响程序的终止
Running:线程正在正常运行;
Stopped:线程已经被停止;
StopRequested:线程正在被要求停止;
Suspended:线程已经被挂起(此状态下,可以通过调用Resume()方法重新运行);
SuspendRequested:线程正在要求被挂起,但是未来得及响应;
Unstarted:未调用Thread.Start()开始线程的运行;
WaitSleepJoin:线程因为调用了Wait(),Sleep()或Join()等方法处于封锁状态;
线程之间的同步
- 关键字lock
lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。此语句的形式如下:
Object thisLock = new Object(); lock (thisLock) { // Critical code section }
下面这段代码来自MSDN,演示了多个线程对同一个对象的操作,保持多个线程之间的同步(http://msdn.microsoft.com/zh-cn/library/c5kehkcz(v=VS.80).aspx)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ThreadLearn { class Account { private Object thisLock = new Object(); int balance; Random r = new Random(); public Account(int initial) { balance = initial; } int WithDraw(int amount) { if (balance < 0) throw new Exception("负数"); lock (thisLock) { //Console.WriteLine(Thread.CurrentThread.Name); if (balance > amount) { Console.WriteLine("Balance before WithDraw: " + balance+" "+Thread.CurrentThread.Name); Console.WriteLine("Amount to WithDraw: -" + amount); balance = balance - amount; Console.WriteLine("Balance after WithDraw: " + balance); return amount; } else { return 0; } } } public void DoTransaction() { for (int i = 0; i < 100; i++) { WithDraw(r.Next(1, 100)); } } } class Program { static void Main(string[] args) { Thread[] thread = new Thread[10]; Account acc = new Account(1000); for (int i = 0; i < 10; i++) { Thread t = new Thread(new ThreadStart(acc.DoTransaction)); thread[i] = t; thread[i].Name = "Thread Number: " + i.ToString(); } for (int i = 0; i < 10; i++) { thread[i].Start(); } Console.ReadLine(); //i.ToString(); } } }
- Monitor
与关键字lock类似,Monitor也用于防止多个线程同时执行指定代码段。事实上,lock就是用Monitor来实现的。
例如:
lock(x) { DoSomething(); }
System.Object obj = (System.Object)x; System.Threading.Monitor.Enter(obj); try { DoSomething(); } finally { System.Threading.Monitor.Exit(obj); }
这两段代码是等价的,lock关键字更加简洁一些。