C\#읽 기 및 쓰기 잠 금 Reader WriterLockSlim 을 어떻게 사용 합 니까?
12920 단어 C#병발 하 다읽 기와 쓰기 자물쇠readwriterlock 용법
어떤 경우 에 한 대상 에 대한 읽 기 횟수 는 수정 횟수 보다 훨씬 많 고 간단 한 lock 방식 으로 자 물 쇠 를 추가 하면 읽 기 효율 에 영향 을 줄 수 있 습 니 다.읽 기와 쓰기 자 물 쇠 를 사용 하면 여러 스 레 드 가 이 대상 을 동시에 읽 을 수 있 고 대상 이 기록 되 어 자 물 쇠 를 차지 할 때 만 막 을 수 있 습 니 다.
쉽게 말 하면 특정한 스 레 드 가 읽 기 모드 에 들 어 갈 때 다른 스 레 드 는 읽 기 모드 에 들 어 갈 수 있 습 니 다.이 스 레 드 가 기록 모드 에 들 어가 야 한다 고 가정 하면 그 는 막 힐 수 밖 에 없습니다.읽 기 모드 가 종 료 될 때 까지
마찬가지 로 어떤 스 레 드 가 기록 모드 에 들 어가 면 다른 스 레 드 는 기록 하 든 읽 든 막 힐 수 있 습 니 다.
쓰기/읽 기 모드 에 들 어 가 는 방법 은 두 가지 가 있 습 니 다.
EnterReadLock 은 쓰기 모드 잠 금 상태 로 들 어 가 려 고 시도 합 니 다.
TryEnterReadLock(Int 32)은 읽 기 모드 잠 금 상태 에 들 어 가 려 고 시도 합 니 다.정수 시간 초 과 를 선택 할 수 있 습 니 다.
EnterWriteLock 은 쓰기 모드 잠 금 상태 로 들 어 가 려 고 시도 합 니 다.
TryEnterWriteLock(Int 32)은 기록 모드 잠 금 상태 에 들 어가 시간 초과 선택 을 시도 합 니 다.
쓰기/읽 기 모드 를 종료 하 는 방법 은 두 가지 가 있 습 니 다.
ExitReadLock 은 읽 기 모드 의 재 귀 계 수 를 줄 이 고 생 성 된 계수 가 0(0)일 때 읽 기 모드 를 종료 합 니 다.
ExitWriteLock 은 쓰기 모드 의 재 귀 계 수 를 줄 이 고 생 성 된 계수 가 0(0)일 때 쓰기 모드 를 종료 합 니 다.
다음은 사용법 을 보 여 드 리 겠 습 니 다.
public class Program
{
static private ReaderWriterLockSlim rwl = new ReaderWriterLockSlim();
static void Main(string[] args)
{
Thread t_read1 = new Thread(new ThreadStart(ReadSomething));
t_read1.Start();
Console.WriteLine("{0} Create Thread ID {1} , Start ReadSomething", DateTime.Now.ToString("hh:mm:ss fff"), t_read1.GetHashCode());
Thread t_read2 = new Thread(new ThreadStart(ReadSomething));
t_read2.Start();
Console.WriteLine("{0} Create Thread ID {1} , Start ReadSomething", DateTime.Now.ToString("hh:mm:ss fff"), t_read2.GetHashCode());
Thread t_write1 = new Thread(new ThreadStart(WriteSomething));
t_write1.Start();
Console.WriteLine("{0} Create Thread ID {1} , Start WriteSomething", DateTime.Now.ToString("hh:mm:ss fff"), t_write1.GetHashCode());
}
static public void ReadSomething()
{
Console.WriteLine("{0} Thread ID {1} Begin EnterReadLock...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
rwl.EnterReadLock();
try
{
Console.WriteLine("{0} Thread ID {1} reading sth...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
Thread.Sleep(5000);//
Console.WriteLine("{0} Thread ID {1} reading end.", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
}
finally
{
rwl.ExitReadLock();
Console.WriteLine("{0} Thread ID {1} ExitReadLock...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
}
}
static public void WriteSomething()
{
Console.WriteLine("{0} Thread ID {1} Begin EnterWriteLock...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
rwl.EnterWriteLock();
try
{
Console.WriteLine("{0} Thread ID {1} writing sth...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
Thread.Sleep(10000);//
Console.WriteLine("{0} Thread ID {1} writing end.", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
}
finally
{
rwl.ExitWriteLock();
Console.WriteLine("{0} Thread ID {1} ExitWriteLock...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
}
}
}
3 번 스 레 드 와 4 번 스 레 드 가 동시에 읽 기 모드 에 들 어 갈 수 있 고 5 번 스 레 드 가 5 초 지나 면(즉 3,4 번 스 레 드 가 읽 기 자 물 쇠 를 종료 한 후)쓰기 모드 에 들 어 갈 수 있 습 니 다.
상기 코드 를 수정 하고 먼저 쓰기 모드 의 스 레 드 2 개 를 연 다음 에 읽 기 모드 스 레 드 를 엽 니 다.코드 는 다음 과 같 습 니 다.
static void Main(string[] args)
{
Thread t_write1 = new Thread(new ThreadStart(WriteSomething));
t_write1.Start();
Console.WriteLine("{0} Create Thread ID {1} , Start WriteSomething", DateTime.Now.ToString("hh:mm:ss fff"), t_write1.GetHashCode());
Thread t_write2 = new Thread(new ThreadStart(WriteSomething));
t_write2.Start();
Console.WriteLine("{0} Create Thread ID {1} , Start WriteSomething", DateTime.Now.ToString("hh:mm:ss fff"), t_write2.GetHashCode());
Thread t_read1 = new Thread(new ThreadStart(ReadSomething));
t_read1.Start();
Console.WriteLine("{0} Create Thread ID {1} , Start ReadSomething", DateTime.Now.ToString("hh:mm:ss fff"), t_read1.GetHashCode());
Thread t_read2 = new Thread(new ThreadStart(ReadSomething));
t_read2.Start();
Console.WriteLine("{0} Create Thread ID {1} , Start ReadSomething", DateTime.Now.ToString("hh:mm:ss fff"), t_read2.GetHashCode());
}
결 과 는 다음 과 같다.3 번 스 레 드 와 4 번 스 레 드 는 모두 쓰기 모드 에 들 어가 야 하지만 3 번 스 레 드 는 쓰기 자 물 쇠 를 먼저 차지 하기 때문에 4 번 스 레 드 는 10s 를 기 다 려 야 들 어 갈 수 밖 에 없다.5 번 스 레 드 와 6 번 스 레 드 는 읽 기 자 물 쇠 를 사용 해 야 하기 때문에 4 번 스 레 드 가 종료 되 어야 자 물 쇠 를 기록 한 후에 야 계속 할 수 있 습 니 다.
TryEnterReadLock 과 TryEnterWriteLock 은 시간 초과 시간 을 설정 할 수 있 습 니 다.이 말 이 실 행 될 때 스 레 드 가 여기 서 막 힙 니 다.이때 자 물 쇠 를 사용 할 수 있다 면 true 로 돌아 갑 니 다.시간 초과 시간 까지 자 물 쇠 를 사용 하지 않 으 면 false 로 돌아 가 자물쇠 의 점용 을 포기 하고 아래 코드 를 계속 실행 합 니 다.
EnterUpgradeableReadLock
Reader WriterLockSlim 클래스 는 읽 기 모드 를 업그레이드 할 수 있 습 니 다.이 방식 과 읽 기 모드 의 차 이 는 EnterWriteLock 이나 TryEnterWriteLock 방법 을 호출 하여 쓰기 모드 로 업그레이드 하 는 것 입 니 다.매번 하나의 스 레 드 만 업그레이드 가능 모드 에 있 기 때문이다.업그레이드 가능 모드 의 스 레 드 에 들 어가 면 읽 기 모드 의 스 레 드 에 영향 을 주지 않 습 니 다.즉,하나의 스 레 드 가 업그레이드 가능 모드 에 들 어가 면 임의의 스 레 드 가 동시에 읽 기 모드 에 들 어가 서 막 히 지 않 습 니 다.기록 자 물 쇠 를 가 져 오 기 를 기다 리 고 있 는 여러 스 레 드 가 있다 면 EnterUpgradeableReadLock 을 실행 하면 스 레 드 가 시간 이 초과 되 거나 기록 자 물 쇠 를 종료 할 때 까지 막 힐 것 입 니 다.
다음 코드 는 읽 기 모드 에서 쓰기 자물쇠 로 업그레이드 하 는 방법 을 보 여 줍 니 다.
static public void UpgradeableRead()
{
Console.WriteLine("{0} Thread ID {1} Begin EnterUpgradeableReadLock...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
rwl.EnterUpgradeableReadLock();
try
{
Console.WriteLine("{0} Thread ID {1} doing sth...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
Console.WriteLine("{0} Thread ID {1} Begin EnterWriteLock...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
rwl.EnterWriteLock();
try
{
Console.WriteLine("{0} Thread ID {1} writing sth...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
Thread.Sleep(10000);//
Console.WriteLine("{0} Thread ID {1} writing end.", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
}
finally
{
rwl.ExitWriteLock();
Console.WriteLine("{0} Thread ID {1} ExitWriteLock...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
}
Thread.Sleep(10000);//
Console.WriteLine("{0} Thread ID {1} doing end.", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
}
finally
{
rwl.ExitUpgradeableReadLock();
Console.WriteLine("{0} Thread ID {1} ExitUpgradeableReadLock...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
}
}
읽 기와 쓰기 자물쇠 가 성능 에 미 치 는 영향 은 뚜렷 하 다.다음 테스트 코드:
public class Program
{
static private ReaderWriterLockSlim rwl = new ReaderWriterLockSlim();
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
List<Task> lstTask = new List<Task>();
for (int i = 0; i < 500; i++)
{
if (i % 25 != 0)
{
var t = Task.Factory.StartNew(ReadSomething);
lstTask.Add(t);
}
else
{
var t = Task.Factory.StartNew(WriteSomething);
lstTask.Add(t);
}
}
Task.WaitAll(lstTask.ToArray());
sw.Stop();
Console.WriteLine(" ReaderWriterLockSlim , :" + sw.Elapsed);
sw.Restart();
lstTask = new List<Task>();
for (int i = 0; i < 500; i++)
{
if (i % 25 != 0)
{
var t = Task.Factory.StartNew(ReadSomething_lock);
lstTask.Add(t);
}
else
{
var t = Task.Factory.StartNew(WriteSomething_lock);
lstTask.Add(t);
}
}
Task.WaitAll(lstTask.ToArray());
sw.Stop();
Console.WriteLine(" lock , :" + sw.Elapsed);
}
static private object _lock1 = new object();
static public void ReadSomething_lock()
{
lock (_lock1)
{
//Console.WriteLine("{0} Thread ID {1} reading sth...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
Thread.Sleep(10);//
//Console.WriteLine("{0} Thread ID {1} reading end.", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
}
}
static public void WriteSomething_lock()
{
lock (_lock1)
{
//Console.WriteLine("{0} Thread ID {1} writing sth...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
Thread.Sleep(100);//
//Console.WriteLine("{0} Thread ID {1} writing end.", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
}
}
static public void ReadSomething()
{
rwl.EnterReadLock();
try
{
//Console.WriteLine("{0} Thread ID {1} reading sth...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
Thread.Sleep(10);//
//Console.WriteLine("{0} Thread ID {1} reading end.", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
}
finally
{
rwl.ExitReadLock();
}
}
static public void WriteSomething()
{
rwl.EnterWriteLock();
try
{
//Console.WriteLine("{0} Thread ID {1} writing sth...", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
Thread.Sleep(100);//
//Console.WriteLine("{0} Thread ID {1} writing end.", DateTime.Now.ToString("hh:mm:ss fff"), Thread.CurrentThread.GetHashCode());
}
finally
{
rwl.ExitWriteLock();
}
}
}
상기 코드 는 500 개의 Task 에 있 습 니 다.모든 Task 는 하나의 스 레 드 탱크 스 레 드 를 차지 합 니 다.그 중에서 20 개의 스 레 드 와 480 개의 읽 기 스 레 드 를 기록 하고 시 뮬 레이 션 을 합 니 다.그 중에서 데 이 터 를 읽 는 데 10ms 가 들 고 쓰기 동작 은 100 ms 가 들 며 각각 lock 방식 과 Reader Writer LockSlim 방식 을 테스트 했다.Reader Writer LockSlim 에 대해 480 개의 스 레 드 를 동시에 읽는다 고 가정 하면 10ms 를 소모 하고 20 개의 기록 작업 은 2000 ms 를 차지 하기 때문에 2010 ms 를 소모 합 니 다.일반적인 lock 방식 은 모두 독점 적 이기 때문에 480 개의 읽 기 작업 은 시간 간 4800 ms+20 개의 기록 작업 2000 ms=6800 ms 를 차지 합 니 다.운행 결 과 는 성능 향상 이 뚜렷 하 다 는 것 을 보 여 주 었 다.이상 은 본 고의 모든 내용 입 니 다.읽 기와 쓰기 자 물 쇠 를 능숙 하 게 활용 하 는 데 도움 이 되 기 를 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
WebView2를 Visual Studio 2017 Express에서 사용할 수 있을 때까지Evergreen .Net Framework SDK 4.8 VisualStudio2017에서 NuGet을 사용하기 때문에 패키지 관리 방법을 packages.config 대신 PackageReference를 사용해야...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.