一个写入线程,三个读取线程,写入和读取不能同时进行,可以并行读取,读取完毕后才能进行下一论和写入,代码如下:static ReaderWriterLock rwLock = new ReaderWriterLock();
static object locker = new object();
static void Main(string[] args)
{
Thread t = null;
for(int i = 0; i < 1; i++)
{
t = new Thread(Writer);
t.Name = i.ToString();
t.Start();
} for(int i = 0; i<3; i++)
{
t = new Thread(Reader);
t.Name = i.ToString();
t.Start();
} Console.ReadLine();
}static void Writer()
{
while(true)
{
try
{
rwLock.AcquireWriterLock(3000);
Console.WriteLine("writer:" + Thread.CurrentThread.Name + " is enter" + " WriterSeqNum:" + rwLock.WriterSeqNum.ToString());
try
{
Thread.Sleep(10000);
}
finally
{
rwLock.ReleaseWriterLock();
Console.WriteLine("writer:" + Thread.CurrentThread.Name + " is exit");
}
}
catch(ApplicationException)
{
Console.WriteLine("writer:" + Thread.CurrentThread.Name + " wait time out");
}
}
}static void Reader()
{
while (true)
{
rwLock.AcquireReaderLock(-1);
Console.WriteLine("reader:" + Thread.CurrentThread.Name + " is enter" + " WriterSeqNum:" + rwLock.WriterSeqNum.ToString());
try
{
Thread.Sleep(5000);
}
finally
{
Console.WriteLine("reader:" + Thread.CurrentThread.Name + " is exit");
rwLock.ReleaseReaderLock();
}
}
}但ReaderWriterLock有这么一个特性:
当写线程队列中有一个线程在等待活动读线程锁被释放时,请求新的读线程锁的线程会排入读线程队列。即使它们能和现有的阅读器锁持有者共享并发访问,也不会给它们的请求授予权限;这有助于防止编写器被阅读器无限期阻止。这就意味着这个要求:读取完毕后才能进行下一论和写入不能被保证,而个人觉得不用ReaderWriterLock实现一个写入三个读取这样的功能代码是很繁琐的,所以才有了ReaderWriterLock这么个东西,但ReaderWriterLock却又没有一种机制来保证读取结束后才进行下一轮写入这样的特性,鸡肋,高手说明一下,会者举一个能够更好说明ReaderWriterLock使用时机的范例代码,3Q
static object locker = new object();
static void Main(string[] args)
{
Thread t = null;
for(int i = 0; i < 1; i++)
{
t = new Thread(Writer);
t.Name = i.ToString();
t.Start();
} for(int i = 0; i<3; i++)
{
t = new Thread(Reader);
t.Name = i.ToString();
t.Start();
} Console.ReadLine();
}static void Writer()
{
while(true)
{
try
{
rwLock.AcquireWriterLock(3000);
Console.WriteLine("writer:" + Thread.CurrentThread.Name + " is enter" + " WriterSeqNum:" + rwLock.WriterSeqNum.ToString());
try
{
Thread.Sleep(10000);
}
finally
{
rwLock.ReleaseWriterLock();
Console.WriteLine("writer:" + Thread.CurrentThread.Name + " is exit");
}
}
catch(ApplicationException)
{
Console.WriteLine("writer:" + Thread.CurrentThread.Name + " wait time out");
}
}
}static void Reader()
{
while (true)
{
rwLock.AcquireReaderLock(-1);
Console.WriteLine("reader:" + Thread.CurrentThread.Name + " is enter" + " WriterSeqNum:" + rwLock.WriterSeqNum.ToString());
try
{
Thread.Sleep(5000);
}
finally
{
Console.WriteLine("reader:" + Thread.CurrentThread.Name + " is exit");
rwLock.ReleaseReaderLock();
}
}
}但ReaderWriterLock有这么一个特性:
当写线程队列中有一个线程在等待活动读线程锁被释放时,请求新的读线程锁的线程会排入读线程队列。即使它们能和现有的阅读器锁持有者共享并发访问,也不会给它们的请求授予权限;这有助于防止编写器被阅读器无限期阻止。这就意味着这个要求:读取完毕后才能进行下一论和写入不能被保证,而个人觉得不用ReaderWriterLock实现一个写入三个读取这样的功能代码是很繁琐的,所以才有了ReaderWriterLock这么个东西,但ReaderWriterLock却又没有一种机制来保证读取结束后才进行下一轮写入这样的特性,鸡肋,高手说明一下,会者举一个能够更好说明ReaderWriterLock使用时机的范例代码,3Q
使用ReaderWriterLock进行资源访问时,如果在某一时刻资源并没有获取写的独占权,
那么可以获得多个读的访问权,单个写入的独占权,
如果某一时刻已经获取了写入的独占权,那么其它读取的访问权必须进行等待
private static ReaderWriterLock m_readerWriterLock = new ReaderWriterLock();
private static void Read()
{
while (true)
{
Console.WriteLine("ThreadName " + Thread.CurrentThread.Name + " AcquireReaderLock");
m_readerWriterLock.AcquireReaderLock(10000);
Console.WriteLine(String.Format("ThreadName : {0} m_int : {1}", Thread.CurrentThread.Name, m_int));
m_readerWriterLock.ReleaseReaderLock();
}
}
private static void Writer()
{
while (true)
{
Console.WriteLine("ThreadName " + Thread.CurrentThread.Name + " AcquireWriterLock");
m_readerWriterLock.AcquireWriterLock(1000);
Interlocked.Increment(ref m_int);
Thread.Sleep(5000);
m_readerWriterLock.ReleaseWriterLock();
Console.WriteLine("ThreadName " + Thread.CurrentThread.Name + " ReleaseWriterLock");
}
} private void button2_Click(object sender, EventArgs e)
{
Thread readThread = new Thread(new ThreadStart(Read));
readThread.Name = "ReadThread1";
Thread readThread2 = new Thread(new ThreadStart(Read));
readThread2.Name = "ReadThread2";
Thread writeThread = new Thread(new ThreadStart(Writer));
writeThread.Name = "WriterThread";
readThread.Start();
readThread2.Start();
writeThread.Start();
readThread.Join();
readThread2.Join();
writeThread.Join();
Console.ReadLine();
}
class Program
{
static ReaderWriterLock rw = new ReaderWriterLock();
static List<int> items = new List<int>();
static Random rand = new Random();
static void Main(string[] args)
{
new Thread(delegate() { while (true) AppendItem(); }).Start();
new Thread(delegate() { while (true) RemoveItem(); }).Start();
new Thread(delegate() { while (true) WriteTotal(); }).Start();
new Thread(delegate() { while (true) WriteTotal(); }).Start();
}
static int GetRandNum(int max)
{
lock (rand) return rand.Next(max);
}
static void WriteTotal()
{
//获取读锁
rw.AcquireReaderLock(10000);
int tot = 0;
foreach (int i in items)
tot += i;
Console.WriteLine(tot);
//释放读锁
rw.ReleaseReaderLock();
}
static void AppendItem()
{
//获取写锁
rw.AcquireWriterLock(10000);
items.Add(GetRandNum(1000));
Thread.SpinWait(400);
//释放写锁
rw.ReleaseWriterLock();
}
static void RemoveItem()
{ //获取写锁
rw.AcquireWriterLock(10000);
if (items.Count > 0)
items.RemoveAt(GetRandNum(items.Count));
//释放写锁
rw.ReleaseWriterLock();
}
}往List中加项目要比移除快一些,这个例子在AppendItem中包含了SpinWait来保持项目总数平衡。