C#专题之线程
5.1 资源访问冲突问题
internal class StateObject
{
private int state = 5;
public void ChangeState()
{
if (state == 5)
{
state++;
Console.WriteLine("state: " + state + " 线程ID:" + Thread.CurrentThread.ManageThreadId);
}
state = 5;
}
}
static void Main(string[] args)
{
StateObject state = new StateObject();
for (int i = 0; i
解决——加锁
internal class StateObject
{
private Object _lock = new Object();
private int state = 5;
public void ChangeState()
{
lock (_lock)
{
if (state == 5)
{
state++;
Console.WriteLine("state: " + state + " 线程ID:" + Thread.CurrentThread.ManageThreadId);
}
state = 5;
}
}
}
异步委托的方式启动线程
static void Test()
{
Console.WriteLine("Test Started");
Console.WriteLine("Test Running");
Thread.Sleep(3000);
Console.WriteLine("Test Completed");
}
delegate void TestDelegate();
static void Main(string[] args)
{
TestDelegate testDelegate = Test;
testDelegate.BeginInvoke(null, null);
Console.WtiteLine("Main Completed");
}
线程的优先级和线程的状态
线程的优先级
在 Thread 类中,可以设置 Priority 属性,以影响线程的基本优先级,Priority 属性是 ThreadPriority 枚举定义的一个值。定义的级别有:Highest、AboveNormal、Normal、BelowNormal 和 Lowest。
(图片来源网络,侵删)
线程的状态
- 获取线程的状态(Running 还是 Unstarted…),当我们通过调用 Thread 对象的 Start() 方法,可以创建线程,但是调用了 Start() 方法之后,新线程不是马上进入 Running 状态,而是处于 Unstarted 状态,只有当操作系统的线程调度器选择了要运行的线程,这个线程的状态才会修改为 Running 状态。我们使用 Thread.Sleep() 方法可以让当前线程休眠进入 WaitSleepJoin 状态。
- 使用 Thread对象的 Abort() 方法可以停止线程。调用这个方法,会在要终止的线程中抛出一个 ThreadAbortException 类型的异常,我们可以 try catch 这个异常,然后在线程终止前做一些清理的工作。
- 如果需要等待线程的结束,可以调用 Thread 对象的 Join() 方法,表示把 Thread 加入进来,暂停当前线程,并把它设置为 WaitSleepJoin 状态,直到加入的线程完成为止。
线程池
static void Main(string[] args) { for (int i = 0; i- 使用线程池启动的线程默认是后台线程
- 如果进程的所有前台线程都结束了,所有的后台线程就会停止,不能把入池的线程改为前台线程。
- 不能给入池的线程设置优先级或名称
- 入池的线程只能用于时间较短的任务,如果线程要一直运行,就应该使用 Thread 类创建一个线程。
死锁问题
internal class StateObject { private Object _lock1 = new Object(); private Object _lock2 = new Object(); private int state1 = 5; private int state2 = 5; public void ChangeState() { Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第1把锁"); lock (_lock1) { lock (_lock2) { Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第2把锁"); if (state1 == 5) { state1++; Console.WriteLine("state: " + state1 + " 线程ID:" + Thread.CurrentThread.ManageThreadId); } state1 = 5; if (state2 == 5) { state2++; Console.WriteLine("state: " + state2 + " 线程ID:" + Thread.CurrentThread.ManageThreadId); } state2 = 5; } } } public void ChangeState() { lock (_lock2) { Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第2把锁"); lock (_lock1) { Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第1把锁"); if (state1 == 5) { state1++; Console.WriteLine("state: " + state1 + " 线程ID:" + Thread.CurrentThread.ManageThreadId); } state1 = 5; if (state2 == 5) { state2++; Console.WriteLine("state: " + state2 + " 线程ID:" + Thread.CurrentThread.ManageThreadId); } state2 = 5; } } } }解决方法——规定相同的拿锁顺序
internal class StateObject { private Object _lock1 = new Object(); private Object _lock2 = new Object(); private int state1 = 5; private int state2 = 5; public void ChangeState() { Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第1把锁"); lock (_lock1) { lock (_lock2) { Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第2把锁"); if (state1 == 5) { state1++; Console.WriteLine("state: " + state1 + " 线程ID:" + Thread.CurrentThread.ManageThreadId); } state1 = 5; if (state2 == 5) { state2++; Console.WriteLine("state: " + state2 + " 线程ID:" + Thread.CurrentThread.ManageThreadId); } state2 = 5; } } } public void ChangeState() { lock (_lock1) { Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第1把锁"); lock (_lock2) { Console.WriteLine(Thread.CurrentThread.ManageThreadId + "拿到了第2把锁"); if (state1 == 5) { state1++; Console.WriteLine("state: " + state1 + " 线程ID:" + Thread.CurrentThread.ManageThreadId); } state1 = 5; if (state2 == 5) { state2++; Console.WriteLine("state: " + state2 + " 线程ID:" + Thread.CurrentThread.ManageThreadId); } state2 = 5; } } } }使用Thread启动线程和传输数据
启动线程
static void Test() { Console.WriteLine("Test Started"); Console.WriteLine("Test Running"); Thread.Sleep(1000); Console.WriteLine("Test Completed"); } static void Main(string[] args) { Thread t = new Thread(Test); t.Start(); Console.WriteLine("Main Completed"); }使用 Lambda 表达式:
static void Main(string[] args) { Thread t = new Thread(() => Console.WriteLine("Child Thread: " + Thread.CurrentThread.ManageThreadId)); t.Start(); Console.WriteLine("Main Completed: " + Thread.CurrentThread.ManageThreadId); }使用匿名方法:
static void Main(string[] args) { Thread t = new Thread(delegate () { Console.WriteLine("Child Thread: " + Thread.CurrentThread.ManageThreadId) }); t.Start(); Console.WriteLine("Main Completed: " + Thread.CurrentThread.ManageThreadId); }传递数据
static void Download(Object x) { string str = o as string; Console.WriteLine(str); } static void Main(string[] args) { Thread t = new Thread(Download); t.Start("http://www.xxx.com"); }Start() 方法只能接收无参的方法或只有一个参数的方法
传递多个数据
public struct Data { public string message; public int age; } static void Download(Object x) { Data data = (Data)o; Console.WriteLine(data.message); Console.WriteLine(data.age); } static void Main(string[] args) { Data data = new Data(); data.message = ""; data.age = 12; Thread t = new Thread(Download); t.Start(data); }任务
static void Main(string[] args) { TaskFactory tf = new TaskFactory(); Task t = tf.StartNew(Test); Thread.Sleep(5000); } static void Test() { for (int i = 0; istatic void Main(string[] args) { Task t = new Task(Test); t.Start(); Thread.Sleep(5000); } static void Test() { for (int i = 0; i连续任务
如果一个任务t1的执行是依赖于另一个任务t2的,那么就需要在这个任务t2执行完毕后才开始执行t1。这个时候我们就可以使用连续任务。
static void FirstDownload() { Console.WriteLine("Downloading ..."); Thread.Sleep(2000); } static void SecondAlert(Task t) { Console.WriteLine("下载完成!"); } static void Main(string[] args) { Task t1 = new Task(FirstDownload); t1.ContinueWith(SecondAlert); t1.Start(); Thread.Sleep(5000); }static void FirstDownload() { Console.WriteLine("Downloading ..."); Thread.Sleep(2000); } static void SecondAlert(Task t) { Console.WriteLine("下载完成!"); } static void Main(string[] args) { Task t1 = new Task(FirstDownload); Task t2 = t1.ContinueWith(SecondAlert); Task t3 = t2.ContinueWith(SecondAlert); t1.Start(); Thread.Sleep(5000);
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!
