我处理主要读取的数据,我希望尽可能高效地执行这些工作,并且我需要提供对它的线程安全访问。
欢迎任何有关我的问题的解释。感谢
答案 0 :(得分:3)
我在C#6 Cookbook中找到了这个答案
使用ReaderWriterLockSlim提供多次读取/单次写入访问,并具有从读取到写入升级锁定的能力。举个例子,假设开发人员正在开始一个新项目。不幸的是,该项目人手不足,因此开发人员必须响应团队中许多其他人的任务。其他每个团队成员也会询问开发人员有关其任务的状态更新,有些甚至可以更改开发人员分配的任务的优先级。通过AddTask方法为开发人员分配任务。为了保护Developer Tasks集合,我们在ReaderWriterLockSlim上使用写锁定,在将任务添加到DeveloperTasks集合时调用EnterWrite Lock,并在添加完成时调用ExitWriteLock:
public void AddTask(DeveloperTask newTask)
{
try
{
Lock.EnterWriteLock();
// if we already have this task (unique by name)
// then just accept the add as sometimes people
// give you the same task more than once :)
var taskQuery = from t in DeveloperTasks
where t == newTask
select t;
if (taskQuery.Count<DeveloperTask>() == 0)
{
Console.WriteLine($"Task {newTask.Name} was added to developer");
DeveloperTasks.Add(newTask);
}
}
finally
{
Lock.ExitWriteLock();
}
}
当项目团队成员需要了解任务的状态时,他们会调用IsTaskDone方法,该方法通过调用EnterReadLock和ExitReadLock在ReaderWriterLockSlim上使用读锁:
public bool IsTaskDone(string taskName)
{
try
{
Lock.EnterReadLock();
var taskQuery = from t in DeveloperTasks
where t.Name == taskName select t;
if (taskQuery.Count<DeveloperTask>() > 0)
{
DeveloperTask task = taskQuery.First<DeveloperTask>();
Console.WriteLine($"Task {task.Name} status was reported.");
return task.Status; } }
finally
{
Lock.ExitReadLock();
}
return false;
}
团队中的某些管理成员有权提高他们分配给开发人员的任务的优先级。他们通过在Developer上调用IncreasePriority方法来实现这一目的。 IncreasePriority使用ReaderWriterLockSlim上的可升级锁定,首先调用EnterUpgradeable Lock方法获取读锁定,然后,如果任务在队列中,则升级到写锁定以调整任务的优先级。一旦调整优先级, 释放写锁定,这会将锁定降级为读锁定,并通过调用ExitUpgradeableReadLock释放该锁定:
public void IncreasePriority(string taskName)
{
try
{
Lock.EnterUpgradeableReadLock();
var taskQuery = from t in DeveloperTasks
where t.Name == taskName select t;
if (taskQuery.Count<DeveloperTask>() > 0)
{ DeveloperTask task = taskQuery.First<DeveloperTask>();
Lock.EnterWriteLock(); task.Priority++;
Console.WriteLine($"Task {task.Name}" + $" priority was increased to {task.Priority}" + " for developer"); Lock.ExitWriteLock();
}
}
finally
{
Lock.ExitUpgradeableReadLock();
}
}
讨论创建ReaderWriterLockSlim是为了替换现有的ReaderWriterLock,原因有很多:•ReaderWriterLock比使用Monitor慢五倍以上。 •ReaderWriterLock的递归语义不是标准的,并且在某些线程重入案例中被破坏。 •升级锁定方法在ReaderWriterLock中是非原子的。虽然ReaderWriterLockSlim只比Monitor快两倍,但它更灵活,并且优先处理写入,因此在“少量写入,多次读取”的情况下,它比Monitor更具可扩展性。还有一些方法可以确定持有什么类型的锁以及等待获取它的线程数。默认情况下,不允许锁定获取递归。如果两次调用EnterReadLock,则会出现LockRecursionException。您可以通过将Lock RecusionPolicy.SupportsRecursion枚举值传递给接受它的ReaderWriterLockSlim的构造函数重载来启用锁定递归。即使可以启用锁定 递归,通常是气馁,因为它使问题复杂化并产生调试无趣的问题。
答案 1 :(得分:1)
所以创建线程的基础
//
Threat t = new Thread (My_Function);
// or
Thread t = new Thread (()=>
{
//your code here
});
t.start();
如果要使读取线程安全,可以在线程内使用“锁定语句”来确保要确保串行访问的资源
lock (Read_resource_object)
{
}
锁的作用是,第一次代码在lock语句上运行时它将“锁定”资源,直到大括号的那个。这并不妨碍其他代码访问该对象,相反,如果任何其他代码调用该资源上的锁,该代码将阻塞,直到锁定它的当前线程解锁它。当然要非常小心,确保你没有得到一个线程锁,这通常发生在你的第一个锁内部以某种方式代码流导致尝试在解锁之前锁定相同的代码。除此之外,我会建议阅读一些关于此的教程,因为多线程和线程安全是困难和复杂的!
同时查找任务以及它们包装线程并提供其他功能。