c#中线程同步(Monitor方法)
这里只是学习笔记~
线程同步(Monitor方法)
线程同步就是协调多个线程间的并发操作,以获得符合预期的、确定的执行结果,消除多线程应用程序执行中的不确定性,
它包含两个方面:1.保护资源(或代码),即确保资源(或代码)同时只能由一个线程(或指定个数的线程)访问,
一般措施是获取锁和释放锁(后面简称锁机制)。
2.协调线程对资源(或代码)的访问顺序,即确定某一资源(或代码)只能先由线程T1访问,再由线程T2访问
一般措施是采用信号量(后面简称信号量机制)。当T2线程访问资源时,必须等待线程T1先访问,线程T1访问完后,发出信号量,通知线程T2可以访问。
1.使用对象本身作为锁对象
Monitor.enter();
xx();//有个缺陷,就是只能使用与引用类型, 解决方法 第二个
Monitor.Exit()
2.使用System.Object作为锁对象(使用这种方式时,需要多创建一个无实际意义的,专用于协调线程的对象)
3.使用System.Type作为锁对象(使用System.Type对象是基于这样一个事实:多次调用typeof(Type)获取的是同一个对象)
线程异常!
在使用monitor的时候可能会出现这种情况,看代码!
public class Test { public string called; public void Record() { called += string.Format("{0}[{1}]", Thread.CurrentThread.Name, DateTime.Now.Millisecond); Console.WriteLine(called); throw new Exception(); // 模拟抛出了异常滴呀; } } class Program { private Test t = new Test(); static void Main(string[] args) { Program p = new Program(); Thread.CurrentThread.Name = "main"; ThreadStart st = new ThreadStart(p.ThreadEntry); Thread td = new Thread(st); td.IsBackground =false; td.Name = "worker"; td.Start(); p.ThreadEntry(); Console.ReadLine(); } void ThreadEntry() { try { Monitor.Enter(typeof(Test)); t.Record(); //首先主线程抛出异常,直接到了catch语句中没有释放它占有的锁 //子线程一直等待, Monitor.Exit(typeof(Test)); } catch { } finally { //解决方法一 //Monitor.Exit(typeof(Test)); 写在finally中滴呀 //解决方法二: //td.IsBackground =true; 设置为后台线程,当前台线程结束(main),后台线程就结束了 //也不用带一种等待了滴呀; } } }
方法三:使用lock
void ThreadEntry() { try { lock (typeof(Test)) { Test.Record(); } } catch { } finally { } }
创建线程安全类型:将lock写在Test.Record()方法里面滴呀;
但是lock方法的缺陷就是锁的粒度很小滴呀;
下面我们进一步来探究。