您的位置:首页 > 编程语言 > C#

《C#高级编程》读书笔记(十五):任务、线程和同步之三 Thread类

2016-08-24 22:38 260 查看
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运行,然后点击“全部中断”,再打开调试->窗口->任务,就可以看到,线程出于死锁状态。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: