ReaderWriterLock(定义支持单个写线程和多个读线程的锁),Mutex(一个同步基元,也可用于进程间同步。 )...

None.gif ReaderWriterLock 用于同步对资源的访问。在任一特定时刻,它允许多个线程同时进行读访问,或者允许单个线程进行写访问。在资源不经常发生更改的情况下,ReaderWriterLock 所提供的吞吐量比简单的一次只允许一个线程的锁(如 Monitor)更高。
None.gif
None.gif在多数访问为读访问,而写访问频率较低、持续时间也比较短的情况下,ReaderWriterLock 的性能最好。多个读线程与单个写线程交替进行操作,所以读线程和写线程都不会长时间阻止。
None.gif
None.gif 一个线程可以持有读线程锁或写线程锁,但是不能同时持有两者。若要获取写线程锁,请使用 UpgradeToWriterLock 和 DowngradeFromWriterLock,而不要通过释放读线程锁的方式获取。
None.gif
None.gif递归锁请求会增加锁上的锁计数。
None.gif
None.gif读线程和写线程将分别排入各自的队列。当线程释放写线程锁时,此刻读线程队列中的所有等待线程都将被授予读线程锁;当已释放所有读线程锁时,写线程队列中处于等待状态的下一个线程(如果存在)将被授予写线程锁,依此类推。换句话说,ReaderWriterLock 在一组读线程和一个写线程之间交替进行操作。
None.gif
None.gif当写线程队列中有一个线程在等待活动读线程锁被释放时,请求新的读线程锁的线程会排入读线程队列。即使它们能和现有的阅读器锁持有者共享并发访问,也不会给它们的请求授予权限;这有助于防止编写器被阅读器无限期阻止。
None.gif
None.gif大多数在 ReaderWriterLock 上获取锁的方法都采用超时值。使用超时可以避免应用程序中出现死锁。例如,某个线程可能获取了一个资源上的写线程锁,然后请求第二个资源上的读线程锁;同时,另一个线程获取了第二个资源上的写线程锁,并请求第一个资源上的读线程锁。如果不使用超时,这两个线程将出现死锁。
None.gif
None.gif如果超时间隔过期并且没有授予锁请求,则此方法通过引发 ApplicationException 将控制返回给调用线程。线程可以捕捉此异常并确定下一步要进行的操作。
None.gif
None.gif超时用毫秒表示。如果使用 System.TimeSpan 指定超时,则所用的值是 TimeSpan 所表示的毫秒整数的总和。下表显示用毫秒表示的有效超时值。
None.gif
None.gif值 
None.gif 说明 
None.gif 
None.gif-1 
None.gif Infinite. 
None.gif 
None.gif
None.gif 无超时。 
None.gif 
None.gif> 0 
None.gif 要等待的毫秒数。 
None.gif 
None.gif
None.gif除了 -1 以外,不允许使用负的超时值。如果要使用 -1 以外的负整数来指定超时,系统将使用零(无超时)。如果指定的 TimeSpan 表示的是 -1 以外的负毫秒数,将引发 ArgumentOutOfRangeException。
None.gif

None.gif //  This example shows a ReaderWriterLock protecting a shared
None.gif
//  resource that is read concurrently and written exclusively
None.gif
//  by multiple threads.
None.gif
None.gif
//  The complete code is located in the ReaderWriterLock
None.gif
//  class topic.
None.gif
using  System;
None.gif
using  System.Threading;
None.gif
None.gif
public   class  Test
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
// Declaring the ReaderWriterLock at the class level
InBlock.gif    
// makes it visible to all threads.
InBlock.gif    
// 声明一个ReaderWriterLock,这样各个线程都可以访问它.
InBlock.gif
    static ReaderWriterLock rwl = new ReaderWriterLock();
InBlock.gif    
// For this example, the shared resource protected by the
InBlock.gif    
// ReaderWriterLock is just an integer.
InBlock.gif
    static int resource = 0;
InBlock.gif
InBlock.gif    
const int numThreads = 26;
InBlock.gif    
static bool running = true;
InBlock.gif    
static Random rnd = new Random();
InBlock.gif
InBlock.gif    
// Statistics.
InBlock.gif
    static int readerTimeouts = 0;
InBlock.gif    
static int writerTimeouts = 0;
InBlock.gif    
static int reads = 0;
InBlock.gif    
static int writes = 0;
InBlock.gif
InBlock.gif    
public static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
// Start a series of threads. Each thread randomly
InBlock.gif        
// performs reads and writes on the shared resource.
InBlock.gif        
// 开启几个线程.每个线程都随机的执行读写共享资源
InBlock.gif
        Thread[] t = new Thread[numThreads];
InBlock.gif        
for (int i = 0; i < numThreads; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            t[i] 
= new Thread(new ThreadStart(ThreadProc));
InBlock.gif            t[i].Name 
= new String(Convert.ToChar(i + 65), 1);
InBlock.gif            t[i].Start();
InBlock.gif            
if (i > 10)
InBlock.gif                Thread.Sleep(
300);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
// Tell the threads to shut down, then wait until they all
InBlock.gif        
// finish.
InBlock.gif        
// 通知线程关闭,等待直到他们都完成
InBlock.gif
        running = false;
InBlock.gif        
for (int i = 0; i < numThreads; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            t[i].Join();
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
// Display statistics.
InBlock.gif
        Console.WriteLine("\r\n{0} reads, {1} writes, {2} reader time-outs, {3} writer time-outs.",
InBlock.gif            reads, writes, readerTimeouts, writerTimeouts);
InBlock.gif        Console.WriteLine(
"Press ENTER to exit.");
InBlock.gif        Console.ReadLine();
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
static void ThreadProc()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
// As long as a thread runs, it randomly selects
InBlock.gif        
// various ways to read and write from the shared 
InBlock.gif        
// resource. Each of the methods demonstrates one 
InBlock.gif        
// or more features of ReaderWriterLock.
InBlock.gif
        while (running)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
double action = rnd.NextDouble();
InBlock.gif            
if (action < .8)
InBlock.gif                ReadFromResource(
10);
InBlock.gif            
else if (action < .81)
InBlock.gif                ReleaseRestore(
50);
InBlock.gif            
else if (action < .90)
InBlock.gif                UpgradeDowngrade(
100);
InBlock.gif            
else
InBlock.gif                WriteToResource(
100);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
// Shows how to request and release a reader lock, and
InBlock.gif    
// how to handle time-outs.
InBlock.gif    
// 显示如何请求和释放读锁,和如何操作过时。
InBlock.gif
    static void ReadFromResource(int timeOut)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
try
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            rwl.AcquireReaderLock(timeOut);
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// It is safe for this thread to read from
InBlock.gif                
// the shared resource.
InBlock.gif
                Display("reads resource value " + resource);
InBlock.gif                Interlocked.Increment(
ref reads);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
finally
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// Ensure that the lock is released.
InBlock.gif
                rwl.ReleaseReaderLock();
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
catch (ApplicationException)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
// The reader lock request timed out.
InBlock.gif
            Interlocked.Increment(ref readerTimeouts);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
// Shows how to request and release the writer lock, and
InBlock.gif    
// how to handle time-outs.
InBlock.gif
    static void WriteToResource(int timeOut)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
try
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            rwl.AcquireWriterLock(timeOut);
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// It is safe for this thread to read or write
InBlock.gif                
// from the shared resource.
InBlock.gif
                resource = rnd.Next(500);
InBlock.gif                Display(
"writes resource value " + resource);
InBlock.gif                Interlocked.Increment(
ref writes);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
finally
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// Ensure that the lock is released.
InBlock.gif
                rwl.ReleaseWriterLock();
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
catch (ApplicationException)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
// The writer lock request timed out.
InBlock.gif
            Interlocked.Increment(ref writerTimeouts);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
// Shows how to request a reader lock, upgrade the
InBlock.gif    
// reader lock to the writer lock, and downgrade to a
InBlock.gif    
// reader lock again.
InBlock.gif    
// 展示如何请求一个读锁,使读锁上升为写锁,然后又重新降为读锁。
InBlock.gif
    static void UpgradeDowngrade(int timeOut)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
try
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            rwl.AcquireReaderLock(timeOut);
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// It is safe for this thread to read from
InBlock.gif                
// the shared resource.
InBlock.gif
                Display("reads resource value " + resource);
InBlock.gif                Interlocked.Increment(
ref reads);
InBlock.gif
InBlock.gif                
// If it is necessary to write to the resource,
InBlock.gif                
// you must either release the reader lock and 
InBlock.gif                
// then request the writer lock, or upgrade the
InBlock.gif                
// reader lock. Note that upgrading the reader lock
InBlock.gif                
// puts the thread in the write queue, behind any
InBlock.gif                
// other threads that might be waiting for the 
InBlock.gif                
// writer lock.
InBlock.gif
                try
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    LockCookie lc 
= rwl.UpgradeToWriterLock(timeOut);
InBlock.gif                    
try
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        
// It is safe for this thread to read or write
InBlock.gif                        
// from the shared resource.
InBlock.gif                        
// 线程读写共享资源是安全的。
InBlock.gif
                        resource = rnd.Next(500);
InBlock.gif                        Display(
"writes resource value " + resource);
InBlock.gif                        Interlocked.Increment(
ref writes);
ExpandedSubBlockEnd.gif                    }

InBlock.gif                    
finally
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        
// Ensure that the lock is released.
InBlock.gif
                        rwl.DowngradeFromWriterLock(ref lc);
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

InBlock.gif                
catch (ApplicationException)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
// The upgrade request timed out.
InBlock.gif
                    Interlocked.Increment(ref writerTimeouts);
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                
// When the lock has been downgraded, it is 
InBlock.gif                
// still safe to read from the resource.
InBlock.gif
                Display("reads resource value " + resource);
InBlock.gif                Interlocked.Increment(
ref reads);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
finally
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// Ensure that the lock is released.
InBlock.gif
                rwl.ReleaseReaderLock();
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
catch (ApplicationException)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
// The reader lock request timed out.
InBlock.gif
            Interlocked.Increment(ref readerTimeouts);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
// Shows how to release all locks and later restore
InBlock.gif    
// the lock state. Shows how to use sequence numbers
InBlock.gif    
// to determine whether another thread has obtained
InBlock.gif    
// a writer lock since this thread last accessed the
InBlock.gif    
// resource.
InBlock.gif    
// 展示如何释放所有的锁和恢复锁的状态.
InBlock.gif    
// 展示利用顺序数字来决定另外一个线程是否获取读锁,当这个线程最后访问资源后.
InBlock.gif
    static void ReleaseRestore(int timeOut)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
int lastWriter;
InBlock.gif
InBlock.gif        
try
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            rwl.AcquireReaderLock(timeOut);
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// It is safe for this thread to read from
InBlock.gif                
// the shared resource. Cache the value. (You
InBlock.gif                
// might do this if reading the resource is
InBlock.gif                
// an expensive operation.)
InBlock.gif
                int resourceValue = resource;
InBlock.gif                Display(
"reads resource value " + resourceValue);
InBlock.gif                Interlocked.Increment(
ref reads);
InBlock.gif
InBlock.gif                
// Save the current writer sequence number.
InBlock.gif
                lastWriter = rwl.WriterSeqNum;
InBlock.gif
InBlock.gif                
// Release the lock, and save a cookie so the
InBlock.gif                
// lock can be restored later.
InBlock.gif
                LockCookie lc = rwl.ReleaseLock();
InBlock.gif
InBlock.gif                
// Wait for a random interval (up to a 
InBlock.gif                
// quarter of a second), and then restore
InBlock.gif                
// the previous state of the lock. Note that
InBlock.gif                
// there is no time-out on the Restore method.
InBlock.gif
                Thread.Sleep(rnd.Next(250));
InBlock.gif                rwl.RestoreLock(
ref lc);
InBlock.gif
InBlock.gif                
// Check whether other threads obtained the
InBlock.gif                
// writer lock in the interval. If not, then
InBlock.gif                
// the cached value of the resource is still
InBlock.gif                
// valid.
InBlock.gif
                if (rwl.AnyWritersSince(lastWriter))
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    resourceValue 
= resource;
InBlock.gif                    Interlocked.Increment(
ref reads);
InBlock.gif                    Display(
"resource has changed " + resourceValue);
ExpandedSubBlockEnd.gif                }

InBlock.gif                
else
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    Display(
"resource has not changed " + resourceValue);
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
finally
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// Ensure that the lock is released.
InBlock.gif
                rwl.ReleaseReaderLock();
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
catch (ApplicationException)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
// The reader lock request timed out.
InBlock.gif
            Interlocked.Increment(ref readerTimeouts);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
// Helper method briefly displays the most recent
InBlock.gif    
// thread action. Comment out calls to Display to 
InBlock.gif    
// get a better idea of throughput.
InBlock.gif
    static void Display(string msg)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.Write(
"Thread {0} {1}.       \r", Thread.CurrentThread.Name, msg);
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif

None.gif 当两个或更多线程需要同时访问一个共享资源时,系统需要使用同步机制来确保一次只有一个线程使用该资源。Mutex 是同步基元,它只向一个线程授予对共享资源的独占访问权。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。
None.gif
None.gif可以使用 WaitHandle.WaitOne 方法请求互斥体的所属权。拥有互斥体的线程可以在对 WaitOne 的重复调用中请求相同的互斥体而不会阻止其执行。但线程必须调用 ReleaseMutex 方法同样多的次数以释放互斥体的所属权。Mutex 类强制线程标识,因此互斥体只能由获得它的线程释放。相反,Semaphore 类不强制线程标识。 
None.gif
None.gif如果线程在拥有互斥体时终止,则称此互斥体被放弃。此互斥体被设置为终止状态,下一个等待的线程获得所属权。如果没有线程拥有互斥体,则互斥体状态为终止。从 .NET Framework 2.0 版开始,需要该互斥体的下一个线程将引发 AbandonedMutexException。在 .NET Framework 2.0 版之前,这样不会引发任何异常。
None.gif
None.gif警告 
None.gif出现遗弃的 Mutex 表明存在严重的编码错误。如果某个线程在未释放互斥体时便退出,受此互斥体保护的数据结构可能处于不一致的状态。如果此数据结构的完整性能得到验证,下一个请求此互斥体所属权的线程就可以处理此异常并继续。 
None.gif 
None.gif
None.gif互斥体有两种类型:局部互斥体和已命名的系统互斥体。如果使用接受名称的构造函数创建 Mutex 对象,则该对象与具有该名称的操作系统对象关联。已命名的系统互斥体在整个操作系统中都可见,可用于同步进程活动。您可以创建多个 Mutex 对象来表示同一个已命名的系统互斥体,也可以使用 OpenExisting 方法打开现有的已命名系统互斥体。
None.gif
None.gif局部互斥体仅存在于您的进程内。您的进程中任何引用局部 Mutex 对象的线程都可以使用它。每个 Mutex 对象都是一个单独的局部互斥体。
None.gif
ExpandedBlockStart.gif ContractedBlock.gif /**/ /*=====================================================================
InBlock.gif  File:      Mutex.cs
InBlock.gif
InBlock.gif  Summary:   Demonstrates how to wait for an object to go signalled
ExpandedBlockEnd.gif
*/

None.gif
None.gif
None.gif
using  System;
None.gif
using  System.Threading;
None.gif
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class  Resource  dot.gif {
InBlock.gif   Mutex m 
= new Mutex();
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif   
public void Access(Int32 threadNum) dot.gif{
InBlock.gif      m.WaitOne();
ExpandedSubBlockStart.gifContractedSubBlock.gif      
try dot.gif{
InBlock.gif         Console.WriteLine(
"Start Resource access (Thread={0})", threadNum);
InBlock.gif         Thread.Sleep(
500);
InBlock.gif         Console.WriteLine(
"Stop  Resource access (Thread={0})", threadNum);
ExpandedSubBlockEnd.gif      }

ExpandedSubBlockStart.gifContractedSubBlock.gif      
finally dot.gif{
InBlock.gif         m.ReleaseMutex();
ExpandedSubBlockEnd.gif      }

ExpandedSubBlockEnd.gif   }

ExpandedBlockEnd.gif}

None.gif
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class  App  dot.gif {
InBlock.gif   
static Int32 numAsyncOps = 5;
InBlock.gif   
static AutoResetEvent asyncOpsAreDone = new AutoResetEvent(false);
InBlock.gif   
static Resource res = new Resource();
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif   
public static void Main() dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif      
for (Int32 threadNum = 0; threadNum < 5; threadNum++dot.gif{
InBlock.gif         ThreadPool.QueueUserWorkItem(
new WaitCallback(UpdateResource), threadNum);
ExpandedSubBlockEnd.gif      }

InBlock.gif
InBlock.gif      asyncOpsAreDone.WaitOne();
InBlock.gif      Console.WriteLine(
"All operations have completed.");
InBlock.gif      Console.ReadLine();
ExpandedSubBlockEnd.gif   }

InBlock.gif
InBlock.gif
InBlock.gif   
// The callback method's signature MUST match that of a System.Threading.TimerCallback 
InBlock.gif   
// delegate (it takes an Object parameter and returns void)
ExpandedSubBlockStart.gifContractedSubBlock.gif
   static void UpdateResource(Object state) dot.gif{
InBlock.gif      res.Access((Int32) state);
InBlock.gif      
if (Interlocked.Decrement(ref numAsyncOps) == 0)
InBlock.gif         asyncOpsAreDone.Set();
ExpandedSubBlockEnd.gif   }

ExpandedBlockEnd.gif}

None.gif

毛毛的小窝

转载于:https://www.cnblogs.com/mjgforever/archive/2007/05/16/748242.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值