using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic; public class SynchronizedCache
{
private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
private Dictionary<int, string> innerCache = new Dictionary<int, string>(); public int Count
{ get { return innerCache.Count; } } public string Read(int key)
{
cacheLock.EnterReadLock();
try
{
return innerCache[key];
}
finally
{
cacheLock.ExitReadLock();
}
} public void Add(int key, string value)
{
cacheLock.EnterWriteLock();
try
{
innerCache.Add(key, value);
}
finally
{
cacheLock.ExitWriteLock();
}
} public bool AddWithTimeout(int key, string value, int timeout)
{
if (cacheLock.TryEnterWriteLock(timeout))
{
try
{
innerCache.Add(key, value);
}
finally
{
cacheLock.ExitWriteLock();
}
return true;
}
else
{
return false;
}
} public AddOrUpdateStatus AddOrUpdate(int key, string value)
{
cacheLock.EnterUpgradeableReadLock();
try
{
string result = null;
if (innerCache.TryGetValue(key, out result))
{
if (result == value)
{
return AddOrUpdateStatus.Unchanged;
}
else
{
cacheLock.EnterWriteLock();
try
{
innerCache[key] = value;
}
finally
{
cacheLock.ExitWriteLock();
}
return AddOrUpdateStatus.Updated;
}
}
else
{
cacheLock.EnterWriteLock();
try
{
innerCache.Add(key, value);
}
finally
{
cacheLock.ExitWriteLock();
}
return AddOrUpdateStatus.Added;
}
}
finally
{
cacheLock.ExitUpgradeableReadLock();
}
} public void Delete(int key)
{
cacheLock.EnterWriteLock();
try
{
innerCache.Remove(key);
}
finally
{
cacheLock.ExitWriteLock();
}
} public enum AddOrUpdateStatus
{
Added,
Updated,
Unchanged
}; ~SynchronizedCache()
{
if (cacheLock != null) cacheLock.Dispose();
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic; public class Example
{
public static void Main()
{
var sc = new SynchronizedCache();
var tasks = new List<Task>();
int itemsWritten = ; // Execute a writer.
tasks.Add(Task.Run( () => { String[] vegetables = { "broccoli", "cauliflower",
"carrot", "sorrel", "baby turnip",
"beet", "brussel sprout",
"cabbage", "plantain",
"spinach", "grape leaves",
"lime leaves", "corn",
"radish", "cucumber",
"raddichio", "lima beans" };
for (int ctr = ; ctr <= vegetables.Length; ctr++)
sc.Add(ctr, vegetables[ctr - ]); itemsWritten = vegetables.Length;
Console.WriteLine("Task {0} wrote {1} items\n",
Task.CurrentId, itemsWritten);
} ));
// Execute two readers, one to read from first to last and the second from last to first.
for (int ctr = ; ctr <= ; ctr++) {
bool desc = Convert.ToBoolean(ctr);
tasks.Add(Task.Run( () => { int start, last, step;
int items;
do {
String output = String.Empty;
items = sc.Count;
if (! desc) {
start = ;
step = ;
last = items;
}
else {
start = items;
step = -;
last = ;
} for (int index = start; desc ? index >= last : index <= last; index += step)
output += String.Format("[{0}] ", sc.Read(index)); Console.WriteLine("Task {0} read {1} items: {2}\n",
Task.CurrentId, items, output);
} while (items < itemsWritten | itemsWritten == );
} ));
}
// Execute a red/update task.
tasks.Add(Task.Run( () => { Thread.Sleep();
for (int ctr = ; ctr <= sc.Count; ctr++) {
String value = sc.Read(ctr);
if (value == "cucumber")
if (sc.AddOrUpdate(ctr, "green bean") != SynchronizedCache.AddOrUpdateStatus.Unchanged)
Console.WriteLine("Changed 'cucumber' to 'green bean'");
}
} )); // Wait for all three tasks to complete.
Task.WaitAll(tasks.ToArray()); // Display the final contents of the cache.
Console.WriteLine();
Console.WriteLine("Values in synchronized cache: ");
for (int ctr = ; ctr <= sc.Count; ctr++)
Console.WriteLine(" {0}: {1}", ctr, sc.Read(ctr)); }
}
// The example displays the following output:
// Task 1 read 0 items:
//
// Task 3 wrote 17 items
//
//
// Task 1 read 17 items: [broccoli] [cauliflower] [carrot] [sorrel] [baby turnip] [
// beet] [brussel sprout] [cabbage] [plantain] [spinach] [grape leaves] [lime leave
// s] [corn] [radish] [cucumber] [raddichio] [lima beans]
//
// Task 2 read 0 items:
//
// Task 2 read 17 items: [lima beans] [raddichio] [cucumber] [radish] [corn] [lime
// leaves] [grape leaves] [spinach] [plantain] [cabbage] [brussel sprout] [beet] [b
// aby turnip] [sorrel] [carrot] [cauliflower] [broccoli]
//
// Changed 'cucumber' to 'green bean'
//
// Values in synchronized cache:
// 1: broccoli
// 2: cauliflower
// 3: carrot
// 4: sorrel
// 5: baby turnip
// 6: beet
// 7: brussel sprout
// 8: cabbage
// 9: plantain
// 10: spinach
// 11: grape leaves
// 12: lime leaves
// 13: corn
// 14: radish
// 15: green bean
// 16: raddichio
// 17: lima beans
构造函数
ReaderWriterLockSlim() |
使用默认属性值初始化 ReaderWriterLockSlim 类的新实例。 |
ReaderWriterLockSlim(LockRecursionPolicy) |
在指定锁定递归策略的情况下初始化 ReaderWriterLockSlim 类的新实例。 |
属性
CurrentReadCount |
获取已进入读取模式锁定状态的独有线程的总数。 |
IsReadLockHeld |
获取一个值,该值指示当前线程是否已进入读取模式的锁定状态。 |
IsUpgradeableReadLockHeld |
获取一个值,该值指示当前线程是否已进入可升级模式的锁定状态。 |
IsWriteLockHeld |
获取一个值,该值指示当前线程是否已进入写入模式的锁定状态。 |
RecursionPolicy |
获取一个值,该值指示当前 ReaderWriterLockSlim 对象的递归策略。 |
RecursiveReadCount |
获取当前线程进入读取模式锁定状态的次数,用于指示递归。 |
RecursiveUpgradeCount |
获取当前线程进入可升级模式锁定状态的次数,用于指示递归。 |
RecursiveWriteCount |
获取当前线程进入写入模式锁定状态的次数,用于指示递归。 |
WaitingReadCount |
获取等待进入读取模式锁定状态的线程总数。 |
WaitingUpgradeCount |
获取等待进入可升级模式锁定状态的线程总数。 |
WaitingWriteCount |
获取等待进入写入模式锁定状态的线程总数。 |
方法
Dispose() |
释放 ReaderWriterLockSlim 类的当前实例所使用的所有资源。 |
EnterReadLock() |
尝试进入读取模式锁定状态。 |
EnterUpgradeableReadLock() |
尝试进入可升级模式锁定状态。 |
EnterWriteLock() |
尝试进入写入模式锁定状态。 |
Equals(Object) |
确定指定的对象是否等于当前对象。 (Inherited from Object) |
ExitReadLock() |
减少读取模式的递归计数,并在生成的计数为 0(零)时退出读取模式。 |
ExitUpgradeableReadLock() |
减少可升级模式的递归计数,并在生成的计数为 0(零)时退出可升级模式。 |
ExitWriteLock() |
减少写入模式的递归计数,并在生成的计数为 0(零)时退出写入模式。 |
GetHashCode() |
作为默认哈希函数。 (Inherited from Object) |
GetType() |
获取当前实例的 Type。 (Inherited from Object) |
MemberwiseClone() |
创建当前 Object 的浅表副本。 (Inherited from Object) |
ToString() |
返回表示当前对象的字符串。 (Inherited from Object) |
TryEnterReadLock(Int32) |
尝试进入读取模式锁定状态,可以选择整数超时时间。 |
TryEnterReadLock(TimeSpan) |
尝试进入读取模式锁定状态,可以选择超时时间。 |
TryEnterUpgradeableReadLock(Int32) |
尝试进入可升级模式锁定状态,可以选择超时时间。 |
TryEnterUpgradeableReadLock(TimeSpan) |
尝试进入可升级模式锁定状态,可以选择超时时间。 |
TryEnterWriteLock(Int32) |
尝试进入写入模式锁定状态,可以选择超时时间。 |
TryEnterWriteLock(TimeSpan) |
尝试进入写入模式锁定状态,可以选择超时时间。 |