线程同步:协调多个线程间的并发操作,以获得符合预期的,确定的执行结果,消除多线程应用程序的不确定性.
使用线程的同步:可以保护资源同时只能由一个线程访问,一般采取的措施是获取锁,释放锁。即锁机制;可以协调线程的访问顺序,即某一资源只能先由线程A访问,再由线程B进行访问。
class Program { private static Thread subthread ; private static int i; static void Main(string[] args) { subthread = new Thread(new ThreadStart(GetShow)); subthread.Start(); //开启线程 GetShow(); //Console.WriteLine("{0}后台线程", Thread.CurrentThread.Name+Thread.CurrentThread.IsBackground+",结束"); } static void GetShow() { Console.WriteLine(i); i++; //Console.WriteLine(i); } }
上面的代码执行时候,出现了两个线程同时访问同一个资源,向控制台输出后去执行i++操作,这样两个线程进来那一时间,i的值没有发生改变依旧是0,但执行i++后的值发生了改变,注释掉下面的输出运行程序发现:先输出2后输出的是1,这也是线程的执行顺序不确定而造成的值的输出顺序有差异。
使用排他锁,通过Monitor进行资源保护
1.使用对象作为锁对象:
class Program { private static Thread subthread ; private static int i; private static object obj = new object(); static void Main(string[] args) { Thread.CurrentThread.Name = "主"; subthread = new Thread(new ThreadStart(GetShow)); subthread.Name = "subject"; subthread.Start(); //开启线程 GetShow(); //Console.WriteLine("{0}后台线程", Thread.CurrentThread.Name+Thread.CurrentThread.IsBackground+",结束"); } static void GetShow() { Monitor.Enter(obj);// 在指定对象上获取排他锁。 Console.WriteLine(Thread.CurrentThread.Name+">>"+i); i++; Console.WriteLine(Thread.CurrentThread.Name+">>"+i); Monitor.Exit(obj); // 释放指定对象上的排他锁。 } }
使用System.Type进行锁对象:
修改上面的方法:运行结果与上面一致。
<span style="white-space:pre"> </span>static void GetShow() { Monitor.Enter(typeof(Program));// 在指定对象上获取排他锁。 Console.WriteLine(Thread.CurrentThread.Name+">>"+i); i++; Console.WriteLine(Thread.CurrentThread.Name+">>"+i); Monitor.Exit(typeof(Program)); // 释放指定对象上的排他锁。 }
使用lock加锁:
如果上面的Monitor.Exit(typeof(Program))前面代码出现异常的话,主线程在执行到异常出会抛出异常,可以通过:try catch finall进行处理:
try { Console.WriteLine(Thread.CurrentThread.Name + ">>" + i); i++; Console.WriteLine(Thread.CurrentThread.Name + ">>" + i); throw new Exception("asdasd"); } catch { } finally { Monitor.Exit(typeof(Program)); // 释放指定对象上的排他锁。 }
使用lock可以进行简化:实现效果和上面一样.
lock (typeof(Program)) { try { Console.WriteLine(Thread.CurrentThread.Name + ">>" + i); i++; Console.WriteLine(Thread.CurrentThread.Name + ">>" + i); throw new Exception("asdasd"); } catch { } }
进行[MethodImpl(MethodImplOptions.Synchronized)]标记
创建线程的安全类型,可以使用[MethodImpl(MethodImplOptions.Synchronized)]进行标记:
[MethodImpl(MethodImplOptions.Synchronized)]//进行标记 static void GetShow() { try { Console.WriteLine(Thread.CurrentThread.Name + ">>" + i); i++; Console.WriteLine(Thread.CurrentThread.Name + ">>" + i); throw new Exception("asdasd"); } catch { } }
使用Monitor协调线程的执行顺序:
class Program { private static Thread subthread ; static void Main(string[] args) { Program p=new Program (); Thread.CurrentThread.Name = "主线程"; subthread = new Thread(new ThreadStart(p.GetShow)); subthread.Name = "子线程"; subthread.Start(); //开启线程 lock (typeof(Program)) { Monitor.Wait(typeof(Program)); // 释放对象上的锁并阻止当前线程,直到它重新获取该锁。 Console.WriteLine(Thread.CurrentThread.Name + "开始执行其他逻辑"); } } void GetShow() { lock (typeof(Program)) { Console.WriteLine(subthread.Name+"线程执行完毕"); Monitor.Pulse(typeof(Program)); //通知等待队列中的线程锁定对象状态的更改。 } } }
时间: 2024-10-18 08:35:17