【多线程-线程同步】

短命女 2022-07-24 10:04 389阅读 0赞

线程同步:协调多个线程间的并发操作,以获得符合预期的,确定的执行结果,消除多线程应用程序的不确定性.

使用线程的同步:可以保护资源同时只能由一个线程访问,一般采取的措施是获取锁,释放锁。即锁机制;可以协调线程的访问顺序,即某一资源只能先由线程A访问,再由线程B进行访问。

  1. class Program
  2. {
  3. private static Thread subthread ;
  4. private static int i;
  5. static void Main(string[] args)
  6. {
  7. subthread = new Thread(new ThreadStart(GetShow));
  8. subthread.Start(); //开启线程
  9. GetShow();
  10. //Console.WriteLine("{0}后台线程", Thread.CurrentThread.Name+Thread.CurrentThread.IsBackground+",结束");
  11. }
  12. static void GetShow()
  13. {
  14. Console.WriteLine(i);
  15. i++;
  16. //Console.WriteLine(i);
  17. }
  18. }

20160519165914724

上面的代码执行时候,出现了两个线程同时访问同一个资源,向控制台输出后去执行i++操作,这样两个线程进来那一时间,i的值没有发生改变依旧是0,但执行i++后的值发生了改变,注释掉下面的输出运行程序发现:先输出2后输出的是1,这也是线程的执行顺序不确定而造成的值的输出顺序有差异。

20160519170234959

使用排他锁,通过Monitor进行资源保护

1.使用对象作为锁对象:

  1. class Program
  2. {
  3. private static Thread subthread ;
  4. private static int i;
  5. private static object obj = new object();
  6. static void Main(string[] args)
  7. {
  8. Thread.CurrentThread.Name = "主";
  9. subthread = new Thread(new ThreadStart(GetShow));
  10. subthread.Name = "subject";
  11. subthread.Start(); //开启线程
  12. GetShow();
  13. //Console.WriteLine("{0}后台线程", Thread.CurrentThread.Name+Thread.CurrentThread.IsBackground+",结束");
  14. }
  15. static void GetShow()
  16. {
  17. Monitor.Enter(obj);// 在指定对象上获取排他锁。
  18. Console.WriteLine(Thread.CurrentThread.Name+">>"+i);
  19. i++;
  20. Console.WriteLine(Thread.CurrentThread.Name+">>"+i);
  21. Monitor.Exit(obj); // 释放指定对象上的排他锁。
  22. }
  23. }

20160519171838036

使用System.Type进行锁对象:

修改上面的方法:运行结果与上面一致。

  1. <span style="white-space:pre"> </span>static void GetShow()
  2. {
  3. Monitor.Enter(typeof(Program));// 在指定对象上获取排他锁。
  4. Console.WriteLine(Thread.CurrentThread.Name+">>"+i);
  5. i++;
  6. Console.WriteLine(Thread.CurrentThread.Name+">>"+i);
  7. Monitor.Exit(typeof(Program)); // 释放指定对象上的排他锁。
  8. }

使用lock加锁:

如果上面的Monitor.Exit(typeof(Program))前面代码出现异常的话,主线程在执行到异常出会抛出异常,可以通过:try catch finall进行处理:

  1. try
  2. {
  3. Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);
  4. i++;
  5. Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);
  6. throw new Exception("asdasd");
  7. }
  8. catch
  9. {
  10. }
  11. finally
  12. {
  13. Monitor.Exit(typeof(Program)); // 释放指定对象上的排他锁。
  14. }

使用lock可以进行简化:实现效果和上面一样.

  1. lock (typeof(Program))
  2. {
  3. try
  4. {
  5. Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);
  6. i++;
  7. Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);
  8. throw new Exception("asdasd");
  9. }
  10. catch { }
  11. }

进行[MethodImpl(MethodImplOptions.Synchronized)]标记

创建线程的安全类型,可以使用[MethodImpl(MethodImplOptions.Synchronized)]进行标记:

20160519173808609

  1. [MethodImpl(MethodImplOptions.Synchronized)]//进行标记
  2. static void GetShow()
  3. {
  4. try
  5. {
  6. Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);
  7. i++;
  8. Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);
  9. throw new Exception("asdasd");
  10. }
  11. catch { }
  12. }

使用Monitor协调线程的执行顺序:

  1. class Program
  2. {
  3. private static Thread subthread ;
  4. static void Main(string[] args)
  5. {
  6. Program p=new Program ();
  7. Thread.CurrentThread.Name = "主线程";
  8. subthread = new Thread(new ThreadStart(p.GetShow));
  9. subthread.Name = "子线程";
  10. subthread.Start(); //开启线程
  11. lock (typeof(Program))
  12. {
  13. Monitor.Wait(typeof(Program)); // 释放对象上的锁并阻止当前线程,直到它重新获取该锁。
  14. Console.WriteLine(Thread.CurrentThread.Name + "开始执行其他逻辑");
  15. }
  16. }
  17. void GetShow()
  18. {
  19. lock (typeof(Program))
  20. {
  21. Console.WriteLine(subthread.Name+"线程执行完毕");
  22. Monitor.Pulse(typeof(Program)); //通知等待队列中的线程锁定对象状态的更改。
  23. }
  24. }
  25. }

20160519180409910

发表评论

表情:
评论列表 (有 0 条评论,389人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java线-线同步简述

    为什么要线程同步 由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问机制上的冲突问题,为了保证数据在方法中被访问时的正确性,在访问时加入锁机制(sy

    相关 线-线同步

    线程同步:协调多个线程间的并发操作,以获得符合预期的,确定的执行结果,消除多线程应用程序的不确定性. 使用线程的同步:可以保护资源同时只能由一个线程访问,一般采取的措施是获取

    相关 线同步

    第一种同步方式:ReentrantLock类 一旦一个线程封锁了锁对象,其他任何线程都无法通过lock语句。当其他线程调用lock时,它们被阻塞,直到第一个线程释放锁对象。如

    相关 Java线线同步

    线程安全问题 在单线程中不会出现线程安全问题,而多线程编程中,如果多个线程同时操作同一个资源,这种资源可以是各种类型的的资源:一个变量、一个对象、一个文件、一个数据库表等