第四十二讲 深入线程-续 (并发线程测试及lock的使用)
来源:互联网 发布:java好用的分页插件 编辑:程序博客网 时间:2024/06/05 15:25
第四十二讲 深入线程-续
4. 后台线程
1. 线程的IsBackground属性是用于将线程设置为后台线程
2. .NET中共有两种类型的线程,一种是前台线程,一种是后台线程
3. 它的区别在于,后台线程会随着主线程的结束而结束,而前台线程,应用程序要等待前台线程结束,应用程序才能结束。当给IsBackground属性赋值true时就指明了你建立的是后台线程,如果你建立时不指明类型,那么默认是前台线程。
5. 线程的优先级
1. 当遇到多个线程抢资源的时候,操作系统要负责调度线程。如果想插队,则需要给线程指定优先级。
2. 优先级相同的多个线程等待使用CPU,线程调度器就会使用一个循环调度规则,将CPU逐个交给线程使用。如果线程是被其他线程抢先了,它就会排在队列的最后。
3. 在Thread类中,可以设置Priority属性,以影响线程的基本优先级。
4. ThreadPriority枚举:
1. Highest
2. AboveeNormal
3. BelowNormal
4. Lowest
6. 并发问题
不同的线程在相同的时间要求被执行。他们之间对资源就会产生并发。
实践(冲突与有序)
7. 锁--lock:用lock语句锁定在线程中共享的变量,另一个线程就必须等待该 锁定的解除
C#为同步访问变量提供了一个非常简单的方式,即使用C#语言的关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许线程进入执行,而其他线程必须等待。在C#中,关键字lock定义如下:
lock(expression)
{
staement_block
}
1. expression代表你希望跟踪的对象,通常是对象引用。
2. 如果你想保护一个类的实例,一般地,你可以使用THIS
3. 如果你想保护一个静态变量(如互斥代码段在一个静态方法内部),一般使用类名就可以了
4. 而staement_block就是互斥段的代码,这段代码在一时刻内只可能被一个线程执行。
4. 后台线程
1. 线程的IsBackground属性是用于将线程设置为后台线程
2. .NET中共有两种类型的线程,一种是前台线程,一种是后台线程
3. 它的区别在于,后台线程会随着主线程的结束而结束,而前台线程,应用程序要等待前台线程结束,应用程序才能结束。当给IsBackground属性赋值true时就指明了你建立的是后台线程,如果你建立时不指明类型,那么默认是前台线程。
5. 线程的优先级
1. 当遇到多个线程抢资源的时候,操作系统要负责调度线程。如果想插队,则需要给线程指定优先级。
2. 优先级相同的多个线程等待使用CPU,线程调度器就会使用一个循环调度规则,将CPU逐个交给线程使用。如果线程是被其他线程抢先了,它就会排在队列的最后。
3. 在Thread类中,可以设置Priority属性,以影响线程的基本优先级。
4. ThreadPriority枚举:
1. Highest
2. AboveeNormal
3. BelowNormal
4. Lowest
6. 并发问题
不同的线程在相同的时间要求被执行。他们之间对资源就会产生并发。
实践(冲突与有序)
7. 锁--lock:用lock语句锁定在线程中共享的变量,另一个线程就必须等待该 锁定的解除
C#为同步访问变量提供了一个非常简单的方式,即使用C#语言的关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许线程进入执行,而其他线程必须等待。在C#中,关键字lock定义如下:
lock(expression)
{
staement_block
}
1. expression代表你希望跟踪的对象,通常是对象引用。
2. 如果你想保护一个类的实例,一般地,你可以使用THIS
3. 如果你想保护一个静态变量(如互斥代码段在一个静态方法内部),一般使用类名就可以了
4. 而staement_block就是互斥段的代码,这段代码在一时刻内只可能被一个线程执行。
8. 死锁:在死锁中,至少有两个线程被挂起,等待对方解除锁定。由于两个线程都在等待对方,就出现了死锁,线程将无限等待下去。
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace Con422{ public class statuTest { int num = 5; public void numTest(int i) { if (num == 5) { num++; //下面这个追踪器里的两个参数里,第一次调用第一个参数,为真时继续向下执行 //第一次参数为假时,调用第二个参数,并提示消息框 System.Diagnostics.Trace.Assert(num == 6, "在当前"+Thread.CurrentThread.Name+"的第"+i + "次循环后发生并发问题!"); } num = 5; } } public class Test { public void TestStatu(object o) { statuTest s = o as statuTest; int i = 0; while (true) { i++; //Thread.Sleep(1);//这个地方不能用阻塞,1个毫秒就会报错了 s.numTest(i); //Console.WriteLine(Thread.CurrentThread.Name+"---"+i+"次"); //lock (s)//有锁了就好多了,但也要考虑到死锁的状况 //{ // s.numTest(i); // Console.WriteLine(Thread.CurrentThread.Name); //} } } } class Program { static Thread t; static void Main(string[] args) { Console.WriteLine("\n****************并发线程测试及lock的使用******************\n"); statuTest s = new statuTest(); for (int i = 0; i < 20; i++) { Console.WriteLine("\n*******开始new第---{0}---个线程******\n",i); //循环new线程出来,所有的线程去调用同一个对象 //new Thread(new Test().TestStatu).Start(s); //使用lock锁 t = new Thread(new Test().TestStatu); t.Name = i.ToString() + "号线程"; t.Start(s); } } }}
补充前面写的实例:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace Con42{ class Program { static Thread newThread; static void Main(string[] args) { Console.WriteLine("我是主线程,开始执行"); //测试结果是,如果新线程为前台线程,当主线程结束时,需要等待新线程结束才退出 //如果新线程为后台线程,那么新线程会随着主线程的结束而结束 newThread = new Thread(newthread); newThread.Name = "新线程";//定义新线程的名字 newThread.IsBackground = false;//非后台线程 newThread.Start(); Console.WriteLine("主线程到这里结束了"); Thread.Sleep(1000); Console.WriteLine("\n****************线程优先级测试******************\n"); //优先级一共有: //ThreadPriority枚举: //1. Highest //2. AboveeNormal //3. BelowNormal //4. Lowest //new几个线程,分别赋于不同的优先级,默认为Normal priorityTest pt=new priorityTest(); Thread t01 = new Thread(pt.Function); t01.Name = "一般优先级线程t01"; t01.Priority = ThreadPriority.Normal;//这个一句可有可无,因为它是默认值 Thread t02 = new Thread(pt.Function); t02.Name = "一般以上优先级线程t02"; t02.Priority = ThreadPriority.AboveNormal; Thread t03 = new Thread(pt.Function); t03.Name = "一般以下优先级线程t03"; t03.Priority = ThreadPriority.BelowNormal; Thread t04 = new Thread(pt.Function); t04.Name = "最低优先级线程t04"; t04.Priority = ThreadPriority.Lowest; Thread t05 = new Thread(pt.Function); t05.Name = "最高优先级t05"; t05.Priority = ThreadPriority.Highest; //结果不如意 //t01.Start(t01);//一般优先级 //t02.Start(t02);//一般以上 //t03.Start(t03);//一般以下 //t04.Start(t04);//最低 //t05.Start(t05);//最高 ////结果不如意,好似跟先后执行的顺序也有关 //t01.Start();//一般优先级 //t02.Start();//一般以上 //t03.Start();//一般以下 //t04.Start();//最低 //t05.Start();//最高 //结果不如意 //t05.Start(t05);//最高 //t02.Start(t02);//一般以上 //t01.Start(t01);//一般优先级 //t03.Start(t03);//一般以下 //t04.Start(t04);//最低 //下面这种方式好些 t05.Start();//最高 t02.Start();//一般以上 t01.Start();//一般优先级 t03.Start();//一般以下 t04.Start();//最低 //测试5秒后,别忘记把开关关上,刚忘关了,CPU四核满载了 Thread.Sleep(3000);//阻塞主线程5秒钟给线程优先级测试 pt.Statu = false; //结果不如人意,CPU并没有按我设置的优先线得出让人满意的结果 Thread.Sleep(1000); Console.WriteLine("\n****************并发线程测试******************\n"); //定义一个线程数组 Thread[] arrayThread = new Thread[10]; //遍历每个线程并实例化,设置线程名 for (int i = 0; i < 10; i++) { arrayThread[i] = new Thread(BingFaTest); arrayThread[i].Name = "线程" + i; } //遍历执行每个线程 foreach (Thread t in arrayThread) { t.Start(); //如果这个地方加阻塞呢,果然好一些 //Thread.Sleep(100); } Console.ReadKey(); } public static void newthread() { Console.WriteLine("我是{0},开始执行",newThread.Name); //Thread.Sleep(3000);//新线程休息2秒钟 Console.WriteLine("{0}也结束了",newThread.Name); } public static void BingFaTest() { Console.WriteLine("\n---------{0}正在打印数字--------\n",Thread.CurrentThread.Name); for (int i = 0; i < 10; i++) { Console.Write("{0}({1})",i,Thread.CurrentThread.Name); } //如果不加这个阻塞,那每个线程会正常运行 //启用这个阻塞,部分打印就会有点小乱了 //Thread.Sleep(500);//稍有阻塞就乱 Random r = new Random(); Thread.Sleep(r.Next());//还是一样稍有阻塞就乱 } } /// <summary> /// 线程优先级测试类 /// </summary> public class priorityTest { bool statu; public bool Statu { set { statu = value; } } public priorityTest() { this.statu = true; } public void Function(object o) { //Thread t = o as Thread; long count=0L;//计数器 while (this.statu) { count++; } //Console.WriteLine("{0},优先级:{1},计数: {2}",t.Name,t.Priority,count.ToString()); Console.WriteLine("{0},优先级:{1},计数: {2}", Thread.CurrentThread.Name, Thread.CurrentThread.Priority, count.ToString()); } }}
0 0
- 第四十二讲 深入线程-续 (并发线程测试及lock的使用)
- 第四十一讲 深入线程(操作线程的,执行,挂起,恢复,关闭 及 Join的用法)
- mina 使用线程池例子及socket并发测试
- 线程中Lock的使用
- 线程并发工具--Lock&Condition
- 线程并发学习----线程阻塞(lock)
- Spring提供的并发线程池测试使用
- 黑马程序员——线程中等待唤醒机制及jdk5版本lock的深入思考
- 深入解析Java并发程序中线程的同步与线程锁的使用
- 深入解析Java并发程序中线程的同步与线程锁的使用
- 线程同步之Lock对象的使用
- Java并发编程的艺术(十二)——线程安全
- 【java并发】线程并发库的使用
- 简单的并发测试以及线程监控
- 线程并发 共享数据及线程并发
- 线程并发处理之lock学习
- 线程并发处理之lock学习
- 线程并发之Lock and Condition
- Flex 上传摄像头拍照、UI保存为图片
- [高精度+递推] uva 10328 Coin Toss
- 通过Key查找Volume的相关过程分析
- 求二叉树的深度
- C#简单工厂模式(文件案例)
- 第四十二讲 深入线程-续 (并发线程测试及lock的使用)
- TrafficServer内存分配器优化
- poj 2411 状态压缩dp
- uva UVA - 1091610916
- cocos2dx 字体
- 优化Myeclipse10 Building Workspace速度慢等问题
- MH370客机搜索有可能从残骸上取得突破
- Java swing 之边界布局
- MongoDB MapReduce java使用