私は大部分が読み込まれているデータを作業しており、これらの作業をできるだけ効率的に実行したいので、スレッドセーフなアクセスを提供する必要があります。どのように私は読み取りアクセスを最適化できますか?
私はC#とスレッディングの初心者です。私の問題についての説明は歓迎されます。おかげ
私は大部分が読み込まれているデータを作業しており、これらの作業をできるだけ効率的に実行したいので、スレッドセーフなアクセスを提供する必要があります。どのように私は読み取りアクセスを最適化できますか?
私はC#とスレッディングの初心者です。私の問題についての説明は歓迎されます。おかげ
私が書くために読んでから、ロックをアップグレードする能力を有する複数の読み出し/シングル書き込みアクセスを与えるためにC#6クックブック
使用ReaderWriterLockSlimでこの答えを見つけました。たとえば、開発者が新しいプロジェクトを開始しているとします。残念なことに、このプロジェクトは人員が不足しているため、開発者はチームの多くの他の個人のタスクに対応する必要があります。他の各チームメンバーは、開発者にタスクのステータス更新を依頼し、開発者が割り当てられているタスクの優先順位を変更することもできます。開発者には、AddTaskメソッドを使用してタスクが割り当てられます。添加が完了したときにExitWriteLockをDeveloperTasksコレクションにタスクを追加したときにEnterWriteロックを呼び出し、我々はReaderWriterLockSlimの書き込みロックを使用する開発者のタスクのコレクションを保護するには、次の
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();
}
}
プロジェクトチームのメンバーが知っておく必要がありますタスクのステータス、彼らはEnterReadLockとExitReadLockを呼び出すことにより、ReaderWriterLockSlimの読み取りロックを使用していますIsTaskDoneメソッドを呼び出す:
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は、Monitorを使用するよりも5倍以上遅かった。 •ReaderWriterLockの再帰セマンティクスは標準ではなく、一部のスレッド再入可能ケースでは破損していました。 •ReaderWriterLockでは、アップグレードロックメソッドが非構造的です。ReaderWriterLockSlimはモニターよりも約2倍遅いですが、柔軟性があり、書き込み優先順位が高いため、「読み書きがほとんどない」シナリオではモニターよりスケーラビリティが高くなります。また、どのタイプのロックが保持されているのか、それを取得するのを待っているスレッドの数を判断する方法もあります。デフォルトでは、ロック取得再帰は許可されていません。 EnterReadLockを2回呼び出すと、LockRecursionExceptionが発生します。 Lock RecusionPolicy.SupportsRecursion列挙値を受け取るReaderWriterLockSlimのコンストラクタオーバーロードにLock RecusionPolicy.SupportsRecursion列挙値を渡して、ロック再帰を有効にすることができます。 ロックを有効にすることは可能ですが、問題を複雑にし、デバッグするのが楽しくない問題が発生するため、一般的には推奨されません。
だから、あなたはあなたがシリアルアクセスを確保するために必要なリソースにスレッド内で「ロックステートメントを使用することができます読み取り、スレッドセーフにしたい場合は、スレッド
//
Threat t = new Thread (My_Function);
// or
Thread t = new Thread (()=>
{
//your code here
});
t.start();
作成の基本
lock (Read_resource_object)
{
}
最初のコードはロックステートメント上で実行され、中括弧の中になるまでリソースを「ロック」します。これにより、他のコードがそのオブジェクトにアクセスするのを防ぎます他のコードはそのリソースをロックし、そのブロックをコードしますロックしている現在のスレッドがロックを解除するまでもちろん、スレッドロックを取得しないように注意する必要があります。通常、最初のロックの内部で何らかの形でコードのフローがロックされる前に同じコードをロックしようとすると発生します。それ以外のところでは、mutliスレッドとスレッドセーフは難しくて複雑なので、私はこれについていくつかのチュートリアルを読むことをお勧めします!
また、タスクを参照するだけでなく、スレッドをラップして追加機能を提供します。