Thread类允许创建前台线程,以及设置线程的优先级。使用Thread类可以创建和控制线程。
在默认情况下,用Thread类创建的线程是前台线程。线程池中的线程总是后台线程。
static void Main(string[] args) { var t1 = new Thread(ThreadMain); t1.Start(); Console.WriteLine("This is the main thread."); Console.ReadKey(); } static void ThreadMain() { Console.WriteLine("Running in a thread."); }
不能保证哪个结果先输出。线程有操作系统调度,每次哪个线程在前面可以不同。
也可以用Lambda表达式:
static void Main(string[] args) { var t1 = new Thread(()=>Console.WriteLine( $"running in a thread,id: {Thread.CurrentThread.ManagedThreadId}")); t1.Start(); Console.WriteLine($"This is the main thread,id:{Thread.CurrentThread.ManagedThreadId}"); Console.ReadKey(); }
1,后台线程
在用Thread类创建线程时,可以设置IsBackground属性,以确定该线程是前台线程还是后台线程。
var t1 = new Thread(ThreadMain) { Name = "MyNewThread",IsBackground = false};
2,线程的优先级
线程有操作系统调度。由线程指定优先级,就可以影响调度顺序。
在Thread类中,可以设置Priority属性,以影响线程的基本优先级。
3,争用条件
如果两个或多个线程访问相同的对象,并且对共享状态的访问没有同步,就会出现争用条件。
用一个例子来说明争用条件:
public class StateObject { private int state = 5; public void ChangeState(int loop) { if (state == 5) { state++; Trace.Assert(state == 6,"Race condition occurred after"+loop+"loops"); } state = 5; } }
public class SampleTask { public void RaceCondition(object o) { Trace.Assert(o is object,"o must be of type StateObject"); StateObject state = o as StateObject; int i = 0; while (true) { state.ChangeState(i++); } } }
static void Main(string[] args) { var state = new StateObject(); for (int i = 0; i < 2; i++) { Task.Run(() => new SampleTask().RaceCondition(state)); } Console.ReadKey(); }
要避免该问题,可以用lock语句锁定在线程中共享的state变量。
只有引用类型才能用于锁定,因为值类型没有SyncBlock字段,lock本质上Monitor.Enter,Monitor.Enter会使值类型装箱,每次lock的是装箱后的对象。
4,死锁
过多的锁定也会有麻烦。在死锁中,至少有两个线程被挂起,并等待对方解除锁定。由于两个线程都在等在对方,就出现了死锁,线程将无限等待下去。
public class SampleTask { private StateObject s1, s2; public SampleTask(StateObject s1, StateObject s2) { this.s1 = s1; this.s2 = s2; } public void Deadlock1() { int i = 0; while (true) { lock (s1) { lock (s2) { s1.ChangeState(i); s2.ChangeState(i++); Console.WriteLine($"still running,{i}"); } } } } public void Deadlock2() { int i = 0; while (true) { lock (s2) { lock (s1) { s1.ChangeState(i); s2.ChangeState(i++); Console.WriteLine($"still running,{i}"); } } } } }
var state1 = new StateObject(); var state2 = new StateObject(); new Task(new SampleTask(state1,state2).Deadlock1).Start(); new Task(new SampleTask(state1, state2).Deadlock2).Start();
F5运行,然后点击“全部中断”,再打开调试->窗口->任务,就可以看到,线程出于死锁状态。