如何优化读取访问

本文关键字:读取 访问 优化 何优化 | 更新日期: 2023-09-27 17:58:31

我处理大部分是读取的数据,我希望尽可能高效地执行这些工作,我需要提供对它的线程安全访问。

欢迎对我的问题进行任何解释。谢谢

如何优化读取访问

所以创建线程的基础知识

//
Threat t = new Thread (My_Function);
// or 
Thread t = new Thread (()=>
{
   //your code here
});
t.start();

如果要使读取线程安全,可以在要确保串行访问的资源上使用线程内的"lock"语句

lock (Read_resource_object)
{
}
lock

的作用是,代码第一次运行在 lock 语句上时,它将"锁定"资源,直到大括号的那时。这不会阻止其他代码访问该对象,相反,如果任何其他代码调用该资源上的锁,则该代码将阻塞,直到锁定它的当前线程解锁它。当然,要非常小心地确保您不会获得线程锁,这通常发生在您的第一个锁内,代码流以某种方式导致在解锁之前尝试锁定相同的代码。除此之外,我建议您阅读一些有关此的教程,因为多线程和线程安全既困难又复杂!

此外,查找任务也会包装线程并提供其他功能。

我在 C# 6 食谱中找到了这个答案

使用 ReaderWriterLockSlim 提供多读/单写访问权限,并能够将锁从 read 升级到 write 。例如,假设开发人员正在启动一个新项目。不幸的是,该项目人手不足,因此开发人员必须响应团队中许多其他人的任务。其他每个团队成员也会要求开发人员更新其任务的状态,有些人甚至可以更改分配给开发人员的任务的优先级。开发人员通过 AddTask 方法分配任务。为了保护开发人员任务集合,我们在ReaderWriterLockSlim上使用写锁定,在将任务添加到开发人员任务集合时调用 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 方法,该方法通过调用 EnterReadLockExitReadLockReaderWriterLockSlim使用读锁定:

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;
}

团队中的某些管理人员有权增加分配给开发人员的任务的优先级。他们通过在开发人员上调用 IncreasePriority 方法来实现此目的。IncreasePriority 首先调用 EnterUpgradeable Lock 方法来获取读锁定,然后,如果任务在队列中,则升级到写锁定以调整任务的优先级,从而在ReaderWriterLockSlim上使用可升级的锁。调整优先级后,写锁定被释放,这会将锁降级回读锁定,并且该锁通过调用 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比使用监控。
  • ReaderWriterLock的递归语义不是标准的,并且在某些线程重入情况下中断。
  • 升级锁定方法在 ReaderWriterLock 中是非原子的。虽然 ReaderWriterLockSlim只比Monitor慢两倍左右,它更灵活,并且优先考虑写入,因此在"很少写入,多次读取"的场景中,它比Monitor更具可扩展性。
  • 还有一些方法可以确定持有哪种类型的锁因为有多少线程正在等待获取它。默认情况下,lock不允许获取递归。如果您调用 EnterReadLock 两次,你会得到一个LockRecursionException.可以通过将 Lock RecusionPolicy.SupportsRecursion 枚举值传递给接受它的构造函数重载ReaderWriterLockSlim来启用锁递归。
  • 即使可以启用锁递归,通常气馁,因为它使事情复杂化并产生以下问题调试起来不好玩。