읽기 / 쓰기 잠금을 사용할 속성이 많이 있습니다. try finally
또는 using
절을 사용하여 구현할 수 있습니다 .
에서 try finally
나는 이전에 잠금을 획득 try
하고 finally
. 에서 using
절, 나는 그것의 폐기 방법에 생성자에서 잠금을 획득 클래스 및 자료를 만들 것입니다.
많은 곳에서 읽기 / 쓰기 잠금을 사용하고 있으므로 .NET보다 간결한 방법을 찾고 있습니다 try finally
. 한 가지 방법이 권장되지 않는 이유 또는 다른 방법보다 더 나은 이유에 대한 몇 가지 아이디어를 듣고 싶습니다.
방법 1 ( try finally
) :
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
get
{
rwlMyLock_m .AcquireReaderLock(0);
try
{
return dtMyDateTime_m
}
finally
{
rwlMyLock_m .ReleaseReaderLock();
}
}
set
{
rwlMyLock_m .AcquireWriterLock(0);
try
{
dtMyDateTime_m = value;
}
finally
{
rwlMyLock_m .ReleaseWriterLock();
}
}
}
방법 2 :
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
get
{
using (new ReadLock(rwlMyLock_m))
{
return dtMyDateTime_m;
}
}
set
{
using (new WriteLock(rwlMyLock_m))
{
dtMyDateTime_m = value;
}
}
}
public class ReadLock : IDisposable
{
private ReaderWriterLock rwl;
public ReadLock(ReaderWriterLock rwl)
{
this.rwl = rwl;
rwl.AcquireReaderLock(0);
}
public void Dispose()
{
rwl.ReleaseReaderLock();
}
}
public class WriteLock : IDisposable
{
private ReaderWriterLock rwl;
public WriteLock(ReaderWriterLock rwl)
{
this.rwl = rwl;
rwl.AcquireWriterLock(0);
}
public void Dispose()
{
rwl.ReleaseWriterLock();
}
}
답변
MSDN에서 문 사용 (C # 참조)
using 문은 개체에 대한 메서드를 호출하는 동안 예외가 발생하더라도 Dispose가 호출되도록합니다. 개체를 try 블록에 넣은 다음 finally 블록에서 Dispose를 호출하여 동일한 결과를 얻을 수 있습니다. 사실 이것은 컴파일러가 using 문을 번역하는 방법입니다. 앞의 코드 예제는 컴파일 타임에 다음 코드로 확장됩니다 (객체의 제한된 범위를 만드는 추가 중괄호에 유의하십시오).
{
Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
((IDisposable)font1).Dispose();
}
}
그래서 기본적으로, 동일한 코드이지만 멋진 자동 null 검사와 변수에 대한 추가 범위가 있습니다 . 또한 문서에는 “IDisposable 개체의 올바른 사용을 보장”한다고 명시되어 있으므로 향후 모호한 경우에 대해 더 나은 프레임 워크 지원을받을 수도 있습니다.
따라서 옵션 2로 이동하십시오.
더 이상 필요하지 않은 직후에 끝나는 범위 내에 변수 가있는 것도 장점입니다.
답변
나는 확실히 두 번째 방법을 선호합니다. 사용 시점에서 더 간결하고 오류 발생 가능성이 적습니다.
첫 번째 경우 코드를 편집하는 사람은 Acquire (Read | Write) Lock 호출과 try 사이에 아무것도 삽입하지 않도록주의해야합니다.
(이와 같은 개별 속성에 대해 읽기 / 쓰기 잠금을 사용하는 것은 일반적으로 과잉입니다. 훨씬 더 높은 수준에서 적용하는 것이 가장 좋습니다. 잠금이 유지되는 시간을 고려할 때 경합 가능성이 매우 작기 때문에 여기에서는 간단한 잠금으로 충분합니다. 읽기 / 쓰기 잠금을 획득하는 것은 단순 잠금보다 비용이 많이 드는 작업입니다.)
답변
두 솔루션 모두 예외를 가리기 때문에 나쁠 가능성을 고려하십시오 .
a가 try
없는 것은 catch
분명히 나쁜 생각입니다. 성명도 마찬가지로 위험한 이유는 MSDN 을 참조하십시오 using
.
Microsoft는 이제 ReaderWriterLock 대신 ReaderWriterLockSlim 을 권장 합니다.
마지막으로 Microsoft 예제에서는 이러한 문제를 방지하기 위해 두 개의 try-catch 블록 을 합니다.
try
{
try
{
//Reader-writer lock stuff
}
finally
{
//Release lock
}
}
catch(Exception ex)
{
//Do something with exception
}
간단하고 일관 적이며 깨끗한 솔루션이 좋은 목표이지만을 사용할 수 없다고 가정하면 lock(this){return mydateetc;}
접근 방식을 재고 할 수 있습니다. 더 많은 정보를 통해 Stack Overflow가 도움이 될 수 있다고 확신합니다 😉
답변
저는 개인적으로 가능한 한 자주 C # “using”문을 사용하지만 언급 된 잠재적 인 문제를 피하기 위해 몇 가지 구체적인 작업을 수행합니다. 설명하기 위해 :
void doSomething()
{
using (CustomResource aResource = new CustomResource())
{
using (CustomThingy aThingy = new CustomThingy(aResource))
{
doSomething(aThingy);
}
}
}
void doSomething(CustomThingy theThingy)
{
try
{
// play with theThingy, which might result in exceptions
}
catch (SomeException aException)
{
// resolve aException somehow
}
}
“using”문을 하나의 메서드로 분리하고 개체의 사용을 “try”/ “catch”블록을 사용하여 다른 메서드로 분리했습니다. 관련 객체에 대해 이와 같은 여러 “using”문을 중첩 할 수 있습니다 (가끔 프로덕션 코드에서 3 ~ 4 개 깊이로 이동합니다).
내 Dispose()
이러한 사용자 정의에 대한 방법에서IDisposable
클래스, 나는 예외 (하지만 오류)를 잡아 (Log4net 사용)을 기록합니다. 이러한 예외가 내 처리에 영향을 미칠 수있는 상황을 본 적이 없습니다. 평소와 같이 잠재적 인 오류는 호출 스택을 전파하고 일반적으로 적절한 메시지 (오류 및 스택 추적)가 기록 된 상태로 처리를 종료 할 수 있습니다.
에서 중대한 예외가 발생할 수있는 상황이 발생하면 Dispose()
해당 상황에 맞게 재 설계 할 것입니다. 솔직히 그런 일이 일어날 지 의심 스럽습니다.
한편, “사용”의 범위와 정리 이점은 제가 가장 좋아하는 C # 기능 중 하나입니다. 그건 그렇고, 저는 Java, C # 및 Python을 기본 언어로 사용하고 여기저기서 많은 다른 언어를 사용합니다. “사용”은 실용적이고 일상적인 일이기 때문에 가장 좋아하는 언어 기능 중 하나입니다. .
답변
세 번째 옵션이 좋아요
private object _myDateTimeLock = new object();
private DateTime _myDateTime;
public DateTime MyDateTime{
get{
lock(_myDateTimeLock){return _myDateTime;}
}
set{
lock(_myDateTimeLock){_myDateTime = value;}
}
}
두 가지 옵션 중 두 번째 옵션은 무슨 일이 일어나고 있는지 가장 깨끗하고 이해하기 쉽습니다.
답변
“속성 무리”및 속성 getter 및 setter 수준의 잠금이 잘못 보입니다. 잠금이 너무 세분화되어 있습니다. 대부분의 일반적인 객체 사용 에서 동시에 둘 이상의 속성에 액세스 하기 위해 잠금을 획득했는지 확인하고 싶을 것 입니다. 귀하의 특정 사례는 다를 수 있지만 다소 의심 스럽습니다.
어쨌든, 속성 대신 객체에 액세스 할 때 잠금을 획득하면 작성해야하는 잠금 코드의 양을 크게 줄일 수 있습니다.