繁体   English   中英

如何优化读取访问?

[英]How can I optimize read access?

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

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

所以创建线程的基础知识

//
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 Cookbook 中找到了这个答案

使用ReaderWriterLockSlim提供多读/单写访问,并具有将锁从read升级到write 例如,假设开发人员正在启动一个新项目。 不幸的是,该项目人手不足,因此开发人员必须响应团队中许多其他人的任务。 其他每个团队成员也会向开发人员询问他们任务的状态更新,有些甚至可以更改分配给开发人员的任务的优先级。 通过AddTask方法为开发人员分配任务。 为了保护我们使用的写锁的开发任务收集ReaderWriterLockSlim ,呼吁EnterWrite锁定添加任务到DeveloperTasks收集和当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 使用ReaderWriterLockSlim上的可升级锁,首先调用EnterUpgradeable Lock 方法获取读锁,然后,如果任务在队列中,则升级为写锁以调整任务的优先级。 一旦调整了优先级,就会释放写锁,这ExitUpgradeableReadLock锁降级回读锁,然后通过调用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更具可扩展性。
  • 还有一些方法可以确定持有哪种类型的锁以及有多少线程正在等待获取它。 默认情况下,不允许lock获取递归。 如果您调用 EnterReadLock 两次,则会收到LockRecursionException 您可以通过将 Lock RecusionPolicy.SupportsRecursion 枚举值传递给接受它的ReaderWriterLockSlim的构造函数重载来启用锁递归。
  • 尽管可以启用锁递归,但通常不鼓励这样做,因为它会使问题复杂化并产生调试不愉快的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM