线程同步及线程用到的锁对象

转载 2012年03月23日 13:44:20

转自:http://blog.csdn.net/ghostbear/article/details/7328686

 

如果程序涉及到多个线程协同完成某项任务,那么你将会面对线程同步的问题。.Net为这类为题提供了很好的解决方案,我们只需要书写少量的代码就能避免线程出现死锁。

线程同步

辅助类  

  1. class ThreadSync 
  2.  
  3.     { 
  4.  
  5.         public long data1; 
  6.  
  7.         public long data2; 
  8.  
  9.   
  10.  
  11.         public void Increase() 
  12.  
  13.         { 
  14.  
  15.             data2++; 
  16.  
  17.         } 
  18.  
  19.  
  20.   
  21.  
  22.     class AlgorithmicTimer 
  23.  
  24.     { 
  25.  
  26.         public DateTime startTime { get; set; } 
  27.  
  28.         public DateTime endTime { get; set; } 
  29.  
  30.   
  31.  
  32.         public void Analyse() 
  33.  
  34.         { 
  35.  
  36.             Console.WriteLine( 
  37.  
  38. string.Format("当前程序共运行了:{0}秒" 
  39.  
  40. , (endTime - startTime).TotalSeconds)); 
  41.  
  42.         } 
  43.  
  44.   
  45.  
  46.   
  47.  
  48.     } 
  49.  


调用代码

  1. ThreadSync myThreadSync = new ThreadSync(); 
  2.  
  3. AlgorithmicTimer timer = new AlgorithmicTimer(); 
  4.  
  5.              
  6.  
  7.     timer.startTime = DateTime.Now; 
  8.  
  9.     for (int i = 0; i < 100000000; i++) 
  10.  
  11.     { 
  12.  
  13.         myThreadSync.Increase(); 
  14.  
  15.  
  16.   
  17.  
  18.     Console.WriteLine(myThreadSync.data2); 
  19.  
  20.     timer.endTime = DateTime.Now; 
  21.  
  22.     timer.Analyse(); 
  23.  
  24.              
  25.  
  26.     myThreadSync.data2 = 0; 
  27.  
  28.     timer.startTime = DateTime.Now; 
  29.  
  30.     Parallel.For(0, 100000000, (index) => 
  31.  
  32.     { 
  33.  
  34.         lock (myThreadSync)  //不加上Lock得到的结果不正确 
  35.  
  36.         { 
  37.  
  38.             myThreadSync.Increase(); 
  39.  
  40.         } 
  41.  
  42. }); 
  43.  
  44.   
  45.  
  46.     Console.WriteLine(myThreadSync.data2); 
  47.  
  48.     timer.endTime = DateTime.Now; 
  49.  
  50.     timer.Analyse(); 


执行结果

 

100000000

当前程序共运行了:1.1740671秒

100000000

当前程序共运行了:11.4436546秒

PV信号量操作

  1. //Semaphore 信号量对象,PV 操作 
  2.  
  3. int threadCount = 6; 
  4.  
  5. int semaphoreCount = 4; 
  6.  
  7. var semaphore = new SemaphoreSlim(semaphoreCount, semaphoreCount); 
  8.  
  9. var threads = new Thread[threadCount]; 
  10.  
  11.  
  12.  
  13. for (int i = 0; i < threadCount; i++) 
  14.  
  15.  
  16.      threads[i] = new Thread(mysemaphore.ThreadMain); 
  17.  
  18.      threads[i].Start(semaphore); 
  19.  
  20.  
  21.  
  22.  
  23. for (int i = 0; i < threadCount; i++) 
  24.  
  25.  
  26.      threads[i].Join(); 
  27.  
  28.  
  29. Console.WriteLine("All threads finished!"); 


Mysemaphore类型

  1. using System; 
  2.  
  3. using System.Collections.Generic; 
  4.  
  5. using System.Linq; 
  6.  
  7. using System.Text; 
  8.  
  9.   
  10.  
  11. using System.Threading; 
  12.  
  13. using System.Threading.Tasks; 
  14.  
  15. using System.Diagnostics; 
  16.  
  17.   
  18.  
  19. namespace chapter20 
  20.  
  21.  
  22.     class mysemaphore 
  23.  
  24.     { 
  25.  
  26.         public static  void ThreadMain(object o) 
  27.  
  28.         { 
  29.  
  30.             SemaphoreSlim semaphore = o as SemaphoreSlim; 
  31.  
  32.             Trace.Assert(semaphore != null, "o must be a Semaphore type"); 
  33.  
  34.             bool isCompleted = false
  35.  
  36.             while (!isCompleted) 
  37.  
  38.             { 
  39.  
  40.                 if (semaphore.Wait(600)) 
  41.  
  42.                 { 
  43.  
  44.                     try 
  45.  
  46.                     { 
  47.  
  48.                         Console.WriteLine("Thread {0} locks the semaphore 
  49.  
  50. ,Current PV:{1}" 
  51.  
  52. , new object[]{Thread.CurrentThread.ManagedThreadId,semaphore.CurrentCount}); 
  53.  
  54.                         
  55.  
  56.                         Thread.Sleep(2000); 
  57.  
  58.                     } 
  59.  
  60.                     finally 
  61.  
  62.                     { 
  63.  
  64.                         semaphore.Release(); 
  65.  
  66.                         Console.WriteLine("Thread {0} release the semaphore,Current PV:{1}", new object[]{Thread.CurrentThread.ManagedThreadId,semaphore.CurrentCount}); 
  67.  
  68.                       
  69.  
  70.                         isCompleted = true
  71.  
  72.                     } 
  73.  
  74.                 } 
  75.  
  76.                 else 
  77.  
  78.                 { 
  79.  
  80.                     Console.WriteLine("Timeout for thread {0},wait again", Thread.CurrentThread.ManagedThreadId); 
  81.  
  82.                 } 
  83.  
  84.             } 
  85.  
  86.         } 
  87.  
  88.     } 
  89.  


执行结果:

 

Thread 9 locks the semaphore,Current PV:3

Thread 10 locks the semaphore,Current PV:2

Thread 11 locks the semaphore,Current PV:1

Thread 12 locks the semaphore,Current PV:0

Timeout for thread 13,wait again

Timeout for thread 14,wait again

Timeout for thread 13,wait again

Timeout for thread 14,wait again

Thread 9 release the semaphore,Current PV:1

Thread 13 locks the semaphore,Current PV:0

Thread 11 release the semaphore,Current PV:2

Timeout for thread 14,wait again

Thread 10 release the semaphore,Current PV:1

Thread 14 locks the semaphore,Current PV:2

Thread 12 release the semaphore,Current PV:3

Thread 13 release the semaphore,Current PV:3

Thread 14 release the semaphore,Current PV:4

All threads finished!

Event类

    解决资源分配问题,当程序释放资源时改变该事件的状态。通知其他程序它释放了资源。

辅助类

   

  1. class Calculator 
  2.  
  3.     { 
  4.  
  5.         private ManualResetEventSlim mEvent; 
  6.  
  7.         public int Result { get; private set; } 
  8.  
  9.         public Calculator(ManualResetEventSlim ev) 
  10.  
  11.         { 
  12.  
  13.             this.mEvent = ev; 
  14.  
  15.         } 
  16.  
  17.   
  18.  
  19.         public void Calculation(object obj) 
  20.  
  21.         { 
  22.  
  23.             Tuple<int, int> data = obj as Tuple<int, int>; 
  24.  
  25.             Console.WriteLine("Task {0} starts calculation" 
  26.  
  27. , Task.CurrentId); 
  28.  
  29.             Thread.Sleep(new Random().Next(3000)); 
  30.  
  31.             Result = data.Item1 + data.Item2; 
  32.  
  33.   
  34.  
  35.             Console.WriteLine("Task {0} is ready", Task.CurrentId); 
  36.  
  37.             mEvent.Set(); 
  38.  
  39.         } 
  40.  
  41.  
  42.   


调用代码:

  

  1. //Event 类 
  2.  
  3.    int taskCount = 4; 
  4.  
  5.    var mEvents = new ManualResetEventSlim[taskCount]; 
  6.  
  7.    var waitHandles = new WaitHandle[taskCount]; 
  8.  
  9.    var calcs = new Calculator[taskCount]; 
  10.  
  11.  
  12.  
  13.    TaskFactory taskFactory = new TaskFactory(); 
  14.  
  15.    for (int i = 0; i < taskCount; i++) 
  16.  
  17.    { 
  18.  
  19.        mEvents[i] = new ManualResetEventSlim(false); 
  20.  
  21.        waitHandles[i] = mEvents[i].WaitHandle; 
  22.  
  23.        calcs[i] = new Calculator(mEvents[i]); 
  24.  
  25.  
  26.  
  27.        taskFactory.StartNew(calcs[i].Calculation, Tuple.Create(i + 1, i + 3)); 
  28.  
  29.  
  30.  
  31.    } 
  32.  
  33.  
  34.  
  35.    for (int i = 0; i < taskCount; i++) 
  36.  
  37.    { 
  38.  
  39.        int index = WaitHandle.WaitAny(waitHandles); 
  40.  
  41.        if (index == WaitHandle.WaitTimeout) 
  42.  
  43.        { 
  44.  
  45.            Console.WriteLine("Timeout!!"); 
  46.  
  47.        } 
  48.  
  49.        else 
  50.  
  51.        { 
  52.  
  53.            mEvents[index].Reset(); 
  54.  
  55.            Console.WriteLine("finished task for {0},result:{1}", index, calcs[index].Result); 
  56.  
  57.        } 
  58.  
  59.  
  60.  
  61.    } 


执行结果:

 

Task 1 starts calculation

Task 3 starts calculation

Task 2 starts calculation

Task 4 starts calculation

Task 2 is ready

Task 3 is ready

Task 4 is ready

finished task for 1,result:6

finished task for 2,result:8

finished task for 3,result:10

Task 1 is ready

finished task for 0,result:4

ReadWriterLockSlim(同步资源的读写)

    呵呵,额对这个东西的产生表示很无解。

 

  1. class MyReadWriterLockSlim 
  2.  
  3.   { 
  4.  
  5.       private static List<int> items = new List<int>() { 0, 1, 2, 3, 4, 5 }; 
  6.  
  7.       private static ReaderWriterLockSlim rwl = new 
  8.  
  9.             ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); 
  10.  
  11.  
  12.  
  13.      public static void ReaderMethod(object reader) 
  14.  
  15.       { 
  16.  
  17.           try 
  18.  
  19.           { 
  20.  
  21.               rwl.EnterReadLock(); 
  22.  
  23.  
  24.  
  25.               for (int i = 0; i < items.Count; i++) 
  26.  
  27.               { 
  28.  
  29.                   Console.WriteLine("reader {0}, loop: {1}, item: {2}"
  30.  
  31.                         reader, i, items[i]); 
  32.  
  33.                   Thread.Sleep(40); 
  34.  
  35.               } 
  36.  
  37.           } 
  38.  
  39.           finally 
  40.  
  41.           { 
  42.  
  43.               rwl.ExitReadLock(); 
  44.  
  45.           } 
  46.  
  47.       } 
  48.  
  49.  
  50.  
  51.      public static void WriterMethod(object writer) 
  52.  
  53.       { 
  54.  
  55.           try 
  56.  
  57.           { 
  58.  
  59.               while (!rwl.TryEnterWriteLock(50)) 
  60.  
  61.               { 
  62.  
  63.                   Console.WriteLine("Writer {0} waiting for the write lock"
  64.  
  65.                         writer); 
  66.  
  67.                   Console.WriteLine("current reader count: {0}"
  68.  
  69.                         rwl.CurrentReadCount); 
  70.  
  71.               } 
  72.  
  73.               Console.WriteLine("Writer {0} acquired the lock", writer); 
  74.  
  75.               for (int i = 0; i < items.Count; i++) 
  76.  
  77.               { 
  78.  
  79.                   items[i]++; 
  80.  
  81.                   Thread.Sleep(50); 
  82.  
  83.               } 
  84.  
  85.               Console.WriteLine("Writer {0} finished", writer); 
  86.  
  87.           } 
  88.  
  89.           finally 
  90.  
  91.           { 
  92.  
  93.               rwl.ExitWriteLock(); 
  94.  
  95.           } 
  96.  
  97.       } 
  98.  
  99.  
  100.  
  101.      public static void Go() 
  102.  
  103.       { 
  104.  
  105.           var taskFactory = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None); 
  106.  
  107.           var tasks = new Task[6]; 
  108.  
  109.           tasks[0] = taskFactory.StartNew(WriterMethod, 1); 
  110.  
  111.           tasks[1] = taskFactory.StartNew(ReaderMethod, 1); 
  112.  
  113.           tasks[2] = taskFactory.StartNew(ReaderMethod, 2); 
  114.  
  115.           tasks[3] = taskFactory.StartNew(WriterMethod, 2); 
  116.  
  117.           tasks[4] = taskFactory.StartNew(ReaderMethod, 3); 
  118.  
  119.           tasks[5] = taskFactory.StartNew(ReaderMethod, 4); 
  120.  
  121.  
  122.  
  123.           for (int i = 0; i < 6; i++) 
  124.  
  125.           { 
  126.  
  127.               tasks[i].Wait(); 
  128.  
  129.           } 
  130.  
  131.       } 
  132.  
  133.   } 


执行结果:

 

reader 1, loop: 0, item: 0

reader 1, loop: 1, item: 1

reader 3, loop: 0, item: 0

Writer 1 waiting for the write lock

current reader count: 3

reader 4, loop: 0, item: 0

Writer 2 waiting for the write lock

reader 1, loop: 2, item: 2

reader 3, loop: 1, item: 1

current reader count: 3

reader 4, loop: 1, item: 1

reader 3, loop: 2, item: 2

reader 1, loop: 3, item: 3

reader 4, loop: 2, item: 2

Writer 1 waiting for the write lock

reader 3, loop: 3, item: 3

current reader count: 3

Writer 2 waiting for the write lock

reader 1, loop: 4, item: 4

reader 3, loop: 4, item: 4

reader 4, loop: 3, item: 3

current reader count: 3

Writer 1 waiting for the write lock

current reader count: 3

reader 3, loop: 5, item: 5

reader 1, loop: 5, item: 5

reader 4, loop: 4, item: 4

reader 4, loop: 5, item: 5

Writer 2 waiting for the write lock

Writer 1 waiting for the write lock

current reader count: 1

reader 2, loop: 0, item: 0

current reader count: 1

reader 2, loop: 1, item: 1

Writer 2 waiting for the write lock

Writer 1 waiting for the write lock

reader 2, loop: 2, item: 2

current reader count: 1

current reader count: 1

reader 2, loop: 3, item: 3

Writer 1 waiting for the write lock

Writer 2 waiting for the write lock

reader 2, loop: 4, item: 4

current reader count: 1

current reader count: 1

reader 2, loop: 5, item: 5

Writer 2 waiting for the write lock

Writer 1 waiting for the write lock

current reader count: 0

current reader count: 0

Writer 1 acquired the lock

Writer 2 waiting for the write lock

current reader count: 0

Writer 2 waiting for the write lock

current reader count: 0

Writer 2 waiting for the write lock

current reader count: 0

Writer 1 finished

Writer 2 acquired the lock

Writer 2 finished

 

今天做到一道面试题:线程安全问题,类锁与对象锁的区别

原文:    http://www.iteye.com/topic/806990 http://www.iteye.com/topic/808550   浅谈java内存模型    ...
  • OrangEJuicE11
  • OrangEJuicE11
  • 2017年05月15日 18:11
  • 585

Java对象锁和类锁全面解析(多线程synchronized关键字)

最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念。最近也是遇到一些问题,不搞清楚锁的概念,很容易碰壁,甚至有些时候自己连用没...
  • u013142781
  • u013142781
  • 2016年06月17日 15:51
  • 13204

基于ACE框架---C++多线程开发总结1,涉及 互斥量、读写锁、条件锁、基于条件锁的线程流水控制

本文对ACE使用的介绍不多,因网上ACE的资料很多,故不进行介绍,而仅使用 当使用多线程进行开发工作的时候,必然会涉及到对公有数据的读写处理。 如果多个线程同时访问某个公有变量,若大部分对其写操作...
  • u014692005
  • u014692005
  • 2016年01月28日 09:55
  • 404

java多线程对象锁、类锁、同步机制详解

1.在java多线程编程中对象锁、类锁、同步机制synchronized详解:     对象锁:在java中每个对象都有一个唯一的锁,对象锁用于对象实例方法或者一个对象实例上面的。     类锁:是用...
  • shuaipu813
  • shuaipu813
  • 2016年12月12日 16:20
  • 1382

Java线程面试题(01) Java中如何检查一个线程是否拥特定对象的锁

考虑一个场景,在运行时你必须找到一个Java线程是否对特定的对象加锁,例如,确认NewsReader线程是否持有NewsPaper对象的锁?如果这个问题出现在任何核心的Java面试中,那么我会自动假设...
  • u010096900
  • u010096900
  • 2017年11月21日 12:50
  • 307

线程中释放锁的方式

# 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {...} 代码段内。 # 调用obj.wait()后,线程A就释放了...
  • songfanxuguirong
  • songfanxuguirong
  • 2014年11月20日 17:35
  • 3365

JAVA--多线程同步,锁对象,条件对象

多线程共享内存引发的问题:     问题引起的原因:线程并不持有资源,资源归进程所持有,多个线程并发执行时候, 线程访问资源的先后顺序无法保证 两个线程同时访问一个资源     这回导致结果的不可预...
  • a284266978
  • a284266978
  • 2015年10月18日 02:08
  • 477

java synchronized的理解以及内置锁和对象锁

在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法。 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识。j...
  • mrsbai
  • mrsbai
  • 2016年02月03日 11:25
  • 2972

多线程:线程状态、synchronized关键字、读写锁、条件对象、Volatile、阻塞队列等小结

多线程:线程状态、synchronized关键字、读写锁、条件对象、Volatile、阻塞队列等小结 关于多线程,在这里做下总结,也方便以后自己查阅。线程和进程的关系应该都知道了,这里不细说。在线程出...
  • nieyanshun_me
  • nieyanshun_me
  • 2015年08月12日 22:45
  • 969

Java的多线程之同步篇一:锁对象、条件对象

一、多线程的同步 根据各线程访问数据的次序,可能会产生讹误的对象。这样一种情况通常称为竞争条件。 1>同步存取(以银行转账为例:) 模拟一个有若干个账户的银行,随机地生成在这些账户之间转换钱款的交易...
  • u014482758
  • u014482758
  • 2016年02月11日 16:43
  • 974
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:线程同步及线程用到的锁对象
举报原因:
原因补充:

(最多只允许输入30个字)