关于多线程学习总结(四) 锁
来源:互联网 发布:spine3.4 破解版 mac 编辑:程序博客网 时间:2024/06/07 05:32
写在前面
在进入锁的学习前来看看Thread的方法,之前一直对这个方法不了解,今天学习了下。在学习之前看两段代码吧:
1 static void Main(string[] args) 2 { 3 Thread thread = new Thread(new ThreadStart(myThread1)); 4 thread.Start(); 5 thread.Join(); //关键这一行 6 Console.WriteLine("主线程"); 7 Console.ReadKey(); 8 } 9 public static void myThread1()10 {11 Thread.Sleep(1000);12 Console.WriteLine("1测试线程{0}",++count1);13 }
先来看看效果再说话(左边截图为5行未被注释,右边为被注释):
在这之前,小弟一直不明白为什么加了上面第5行与不加第五行区别是什么,今天终于知道了,原来是线程之间原本并行执行通过使用Join()使其串行化,在这个例子里myThread1()被调用,而此方法存在一个线程阻塞,此时先打印“主线程”(上 右图);然而调用了Join()方法,使其原本并行化的线程串行化,所以主线程必须等待子线程执行完才能执行,此时先打印“1测试线程1”(上 左图)。<以上的串行与并行用词有点不严谨,主要事为了方便理解而已>
进入锁的学习
此句网上COPY来的:我们抛开.NET环境看线程同步,无非是执行两种操作:一是互斥/加锁,目的是保证临界区代码操作的“原子性”;另一种是信号灯操作,目的是保证多个线程按照一定顺序执行,如生产者线程要先于消费者线程执行。
暂时先脑海中留点锁的印象就好啦!下面介绍两个类:
Monitor类
通过查MSDN我们可以发现Monitor类一共有17个方法,但是这17个方法并不是都常用,下面我简单列举几个介绍并结合实例理解理解:
一、Enter()与Exit()
在我看来它目前最主要的功能是设置边界,使原本并行执行的线程顺序化,此句小弟断章取义,不对请指正
1 static void Main(string[] args) 2 { 3 for (int i = 0; i < 15; i++) 4 { 5 Thread thread = new Thread(new ThreadStart(myThread1)); 6 thread.Start(); 7 } 8 Console.WriteLine("主线程"); 9 Console.ReadKey();10 }11 static object ob = new object();12 static int count1 = 0;13 public static void myThread1()14 {15 Monitor.Enter(ob); //作用域开始16 Thread.Sleep(10);17 Console.WriteLine("1测试线程{0}", ++count1);18 Monitor.Exit(ob); //作用域结束19 }
看看效果再说话(左边截图为使用Enter()和Exit(),右边木有用):
看到区别木有,话说程序员都是聪明的班子,哈哈哈、、、、
二、Wait()与Pulse()
我们先来看看MSDN的官方介绍
Wait()——释放对象上的锁并阻止当前线程,直到它重新获取该锁
Pulse()——通知等待队列中的线程锁定对象状态的更改
简而言之,Wait()方法就是暂时释放资源锁,线程进入等待队列,此时其它线程获取资源锁;Pulse()方法则是唤醒等待队列中的线程,重新得到资源锁。
1 static void Main(string[] args) 2 { 3 for (int i = 0; i < 5; i++) 4 { 5 Thread thread = new Thread(new ThreadStart(myThread1)); 6 thread.Start(); 7 Thread thread1 = new Thread(new ThreadStart(myThread2)); 8 thread1.Start(); 9 }10 Console.WriteLine("主线程");11 }12 static object ob = new object(); 13 static int count1 = 0;14 static int count2 = 0;15 public static void myThread1()16 {17 Monitor.Enter(ob);18 Thread.Sleep(10);19 Console.WriteLine("1测试线程{0}", ++count1);20 Monitor.Wait(ob);21 Console.WriteLine("wait");22 Monitor.Pulse(ob);23 Monitor.Exit(ob);24 }25 public static void myThread2()26 {27 Monitor.Enter(ob);28 Thread.Sleep(10);29 Console.WriteLine("2测试线程{0}", ++count2);30 Monitor.Wait(ob);31 Console.WriteLine("wait2");32 Monitor.Pulse(ob);33 Monitor.Exit(ob);34 }
运行结果如下图:
上面打印交替次数是没有规律的,每次都会有偏差
再总结几点:
1.Monitor.Pulse()调用后线程还是会执行下一行代码,不会执行另一个线程,除非再调用Monitor.Wait()让线程进入等待状态
2.只有锁的当前所有者可以使用 Pulse 向等待对象发出信号
3.当前拥有指定对象上的锁的线程调用此方法以便向队列中的下一个线程发出锁的信号。接收到脉冲后,等待线程就被移动到就绪队列中。 在调用 Pulse 的线程释放锁后,就绪队列中的下一个线程(不一定是接收到脉冲的线程)将获得该锁(此句来自MSDN)
ReaderWriterLock类
说句实话,这个类我还真不太熟悉,简单介绍我知道的吧!
我们都知道我们日常代码中,绝大部分都是读取,少部分为写入,而我们前面学习的Monitor类在这里就有些不适合了,因此就出现了ReaderWriterLock这个类,它的好处就是起到,并实现了”写入串行“,”读取并行“的神奇效果。
- 关于多线程学习总结(四) 锁
- 关于多线程学习总结(四) 锁
- 关于多线程学习总结(四) 锁
- 多线程学习(四)
- 多线程学习(四)
- 黑马程序员_多线程学习总结(四)
- 总结iOS 多线程学习过程四
- 多线程总结(四)volatile
- 多线程学习总结(四)——实现多线程的方法之Callable和Futura
- 关于多线程学习总结(五) 线程池
- 关于多线程学习总结(一) 基本概念了解
- 关于多线程学习总结(三) 线程简单基本操作
- 关于多线程学习总结(五) 线程池
- 多线程学习笔记(四)
- 学习总结(四)
- C#编程总结(四)多线程应用
- 关于Java多线程和并发运行的学习(四)——之Condition
- 关于Java多线程和并发运行的学习(四)——之Semaphore
- 多媒体开发指南
- padding和margin的异同点
- 让代码飞一会儿,超级有用的CSS编码工具集
- 强烈推荐!”计算机中的数学“系列视频
- 第四周13/03/31
- 关于多线程学习总结(四) 锁
- [每日一题] OCP1z0-047 :2013-07-19 Rules of Precedence――括号的使用.................8
- UITableView的常用方法与示例
- 爱上IFTTT无法自拔 --[建立你的网络服务秘书]
- 使用堆栈实现括号的匹配
- TPS和QPS的区别
- android开发中常用到的设置
- 将json合适字符串转换为json对象
- 做个文艺的IT人员——今日工作总结-2013.07.18