최근에 C#에서 제공하는 UpgradeableReadLock 구조가 생각 나게되어 실제로 사용할 때 분별하려고합니다.UpgradeableReadLock에 대한 적법한 사용 사례
예를 들어 많은 클래스에서 많이 읽히는 설정 캐시가 있지만 결정적이지 않은 조건 집합을 기반으로 주기적으로 매우 낮은 빈도로 업데이트해야합니다.
List<Setting> cachedSettings = this.GetCachedSettings(sessionId);
lock(cachedSettings)
{
bool requiresRefresh = cachedSettings.RequiresUpdate();
if(requiresRefresh)
{
// a potentially long operation
UpdateSettings(cachedSettings, sessionId);
}
return cachedSettings;
}
을하거나 UpgradeableReadLock을 사용합니다 :
는 단순히과 같이 고정하는 것이 더 나을
public class SomeRepitory {
private ReaderWriterLockSlim _rw = new ReaderWriterLockSlim();
public List<Setting> GetCachedSettings(string sessionId)
{
_rw.EnterUpgradeableReadLock();
List<Setting> cachedSettings = this.GetCachedSettings(sessionId);
bool requiresRefresh = cachedSettings.RequiresUpdate();
if(requiresRefresh)
{
_rw.EnterWriteLock();
UpdateSettings(cachedSettings, sessionId);
_rw.ExitWriteLock();
}
_rw.ExitUpgradeableReadLock();
return cachedSettings;
}
아마도 나를 혼란 무엇 대부분은 쓰기 블록 외부에서 업데이트가 필요한지 확인하는 방법입니다.
while (true)
{
int newNumber = GetRandNum (100);
_rw.EnterUpgradeableReadLock();
if (!_items.Contains (newNumber))
{
_rw.EnterWriteLock();
_items.Add (newNumber);
_rw.ExitWriteLock();
Console.WriteLine ("Thread " + threadID + " added " + newNumber);
}
_rw.ExitUpgradeableReadLock();
Thread.Sleep (100);
}
나의 이해는이 동시에 허용되는
: 내 위의 예에서 나는 새로 고침이 요구되는 검사,하지만 난 "C# 5.0 간단히 말해서"의 예를 사용합니다 단순화 할 때 말하는거다 쓰레드가 쓰여질 필요가 없다면 읽지 만 둘 이상의 쓰레드가 같은 난수로 끝나고!_items.Contains(newNumber)
을 결정한다면? 이 이해를 감안할 때 이것은 동시 읽기 허용해야합니다 (물론 내가 잘못 이해 한 경우 올바른) .. 쓰기 잠금을 얻 자마자 동시에 읽을 수있는 모든 스레드가 일시 중단되고 강제로 다시 시작해야합니다.
_rw.EnterUpgradeableReadLock();
의 시작 부분에?
하지만 동일한 세션/컨텍스트에 대해 두 개의 스레드가 쓰기 잠금을 얻기 전에 RequiresUpdate를 확인하고 requiresRefresh 값이 true 인 두 개의 스레드로 끝나면 ... 그러면 UpdateSettings 메서드 인 a 잠재적으로 비교적 오래 실행하는 방법, 결국 두 번 전화 받고? – Jordan
쓰기 잠금 스레드가 모든 읽기 잠금을 완료 할 때까지 대기하는 경우 @Martin이 게시 한 코드는 _items가 비어 있고 스레드 1과 2가 판독기 잠금을 입력하고 스레드 1은 쓰기 잠금을 입력하려고 시도하고 스레드 2가 대기합니다. 완료되면 스레드 2도 쓰기 잠금을 입력하려고 시도하고 완료되지 않음 - 데드락. 아니면 내가 틀렸어? 편집 : Conclustions 잠금 (chacheSettings)은 느리지 만 방탄입니다 :) –
@RytisI, 아주 좋은 질문입니다! 그러나 나는이 패턴을 많이 사용했고 그러한 시나리오에서는 결코 교착 상태를 보지 못했습니다. 필자는 이것이 EnterUpgradableReadLock()이 EnterReadlock()과 별도로 존재하는 이유라고 생각합니다. 업그레이드 가능한 잠금 장치가 WriteLock()을 입력하면 쓰기 큐에있는 작성기 (있는 경우)에 대한 잠금을 해제합니다. 대기열에 기록기가 없으면 쓰기 잠금을 획득합니다. 비록이 행동에서 나는 잘 모르겠지만. 그냥 추측 ... –