정적 변수는 스레드 안전합니까? C#
DataTables를 저장하는 클래스를 만들고 싶습니다. 이렇게 하면 응용 프로그램에서 검색할 때마다 세부 정보 목록을 가져올 수 없습니다.따라서 이 작업은 한 번 수행해야 합니다. 아래 코드가 수행하는 것으로 알고 있습니다. 하지만 스레드 세이프인지는 잘 모르겠습니다.
아래 코드는 3계층 애플리케이션의 비즈니스 계층 섹션에 있으며 데이터 테이블을 프레젠테이션 계층으로 반환합니다.
public class BusinessLayerHandler
{
public static DataTable unitTable;
public static DataTable currencyTable;
public static DataTable GetUnitList()
{
//import lists each time the application is run
unitTable = null;
if (unitTable == null)
{
return unitTable = DatabaseHandler.GetUnitList();
}
else
{
return unitTable;
}
}
public static DataTable GetCurrencyList()
{
//import lists each time the application is run
currencyTable = null;
if (currencyTable == null)
{
return currencyTable = DatabaseHandler.GetCurrencyList();
}
else
{
return currencyTable;
}
}
도움을 주시면 감사하겠습니다. 데이터 테이블을 캐시하는 더 좋은 방법이 있다면 알려주시기 바랍니다.
업데이트:
당신의 의견 덕분에, 제가 올바르게 이해했다면, 이것이 제안된 방법입니다.
public class BusinessLayerHandler
{
private static DataTable unitTable;
private static DataTable currencyTable;
private static readonly object unitTableLock = new object();
private static readonly object currencyTableLock = new object();
public static DataTable GetUnitList()
{
//import lists each time the application is run
//unitTable = null;
lock (unitTableLock)
{
if (unitTable == null)
{
return unitTable = DatabaseHandler.GetUnitList();
}
}
return unitTable;
}
public static DataTable GetCurrencyList()
{
//import lists each time the application is run
lock (currencyTableLock)
{
if (currencyTable == null)
{
return currencyTable = DatabaseHandler.GetCurrencyList();
}
}
return currencyTable;
}
}
한 번 로드하고 참조를 유지하기만 하면 됩니다.변수가 null이면 변수를 초기화하기만 하면 됩니다.Null 확인, 잠금 및 다시 Null 확인을 Double Check Locking이라고 하며 사용자에게 적합합니다.별도의 잠금 개체를 제공하는 것이 가장 좋습니다. 따라서 잠금의 세부적인 부분을 효과적으로 제어할 수 있습니다.
이것이 사람들이 내부의 가치를 변형시키는 것을 막지는 않습니다.DataTable
동시에 정적 멤버를 초기화하려는 사람들을 막을 뿐입니다.
private static readonly object UnitTableLock = new object();
private static DataTable unitTable;
private static bool _ready = false;
public static DataTable GetUnitList()
{
if (!_ready)
{
lock (UnitTableLock)
{
if (!_ready)
{
unitTable = new DataTable; //... etc
System.Threading.Thread.MemoryBarrier();
_ready = true;
}
}
}
return unitTable;
}
의 결과에서만 읽힙니다.GetUnitList
절대 편지를 쓰지 않습니다.
http://en.wikipedia.org/wiki/Double-checked_locking 을 참조하여 수정됨
Double Check Locking은 그 이후로 .net 프레임워크 4.0에서 구현된 클래스로 추가할 가치가 있다고 생각했습니다. 따라서 클래스에 잠금을 기본적으로 포함시키려면 다음과 같이 사용할 수 있습니다.
public class MySingleton
{
private static readonly Lazy<MySingleton> _mySingleton = new Lazy<MySingleton>(() => new MySingleton());
private MySingleton() { }
public static MySingleton Instance
{
get
{
return _mySingleton.Value;
}
}
}
그것들은 스레드 세이프가 아닙니다.예를 들어, 잠금 연산자를 사용하여 논리 스레드를 안전하게 만드는 것을 고려해야 합니다.
.net 4에 있는 경우 데이터 테이블에서 ThreadLocal 래퍼를 사용할 수 있습니다.
정적 변수는 스레드 자체로 안전하지 않습니다.나사산 안전을 염두에 두고 설계해야 합니다.
시작할 수 있는 좋은 링크가 있습니다. http://en.csharp-online.net/Singleton_design_pattern%3A_Thread-safe_Singleton
이와 별도로 기존 DataTable보다 더 현대적인 접근 방식을 사용할 것을 강력히 권장합니다.엔티티 프레임워크 또는 NHibernate를 확인하십시오.이를 데이터 계층에 구현하면 나머지 소프트웨어에서 데이터베이스 세부 정보를 숨기고 상위 수준의 추상화(POCO 개체)에서 작동할 수 있습니다.
당신은 괜찮아야 할 것 같아요.2개의 스레드가 데이터 테이블이 null임을 결정하고 둘 다 테이블을 읽지만 하나만 할당할 수 있습니다.unitTable
/currencyTable
마지막으로 참조하십시오. 따라서 최악의 경우 두 번 이상 초기화합니다.하지만 일단 준비가 되면 당신이 좋을 것 같아요.당신이 그들에게 편지를 쓰지 않는 한.극장은 일관성 없는 상태로 남을 수 있습니다.
만약 당신이 더블을 피하고 싶다면 당신은 전체 게터 코드를 포장할 수 있습니다.lock
진술.이것은 싱글톤을 초기화하는 것과 비슷합니다.
또한 참조를 다시 null로 설정하여 강제로 새로 고칠 수 있는 방법을 추가합니다.
GJ
데이터 테이블이 읽기 전용인 경우 데이터 테이블을 채울 때 잠가야 하며 변경되지 않으면 스레드 안전합니다.
public class BusinessLayerHandler
{
public static DataTable unitTable;
public static DataTable currencyTable;
private static readonly object unitTableLock = new object();
private static readonly object currencyTableLock = new object();
public static DataTable GetUnitList()
{
//import lists each time the application is run
lock(unitTableLock)
{
if (unitTable == null)
{
unitTable = DatabaseHandler.GetUnitList();
}
}
return unitTable;
}
public static DataTable GetCurrencyList()
{
//import lists each time the application is run
lock(currencyTableLock)
{
if (currencyTable == null)
{
currencyTable = DatabaseHandler.GetCurrencyList();
}
}
return currencyTable;
}
}
이 룩업에서 정말로 높은 성능이 필요한 경우 매번 전체 잠금 대신 ReaderWriterLockSlim 클래스를 사용하여 응용 프로그램에서 발생하는 대기 횟수를 제한할 수 있습니다.
http://kenegozi.com/blog/2010/08/15/readerwriterlockslim-vs-lock 에서 잠금과 ReaderWriterLockSlim의 차이점에 대한 짧은 기사를 확인하십시오.
편집: (아래 설명에 대한 답변)
unitTableLock 개체는 의 모니터 클래스가 동기화할 핸들처럼 사용됩니다.
의 판독 및 동기화에 대한 전체 개요를 확인할 수 있습니다.NET 프레임워크 이 매우 광범위한 튜토리얼 http://www.albahari.com/threading/ 을 소개합니다.
언급URL : https://stackoverflow.com/questions/6941181/are-static-variables-thread-safe-c-sharp
'programing' 카테고리의 다른 글
마리아DB.15일보다 오래된 테이블에서 행을 삭제하는 트리거 만들기 (0) | 2023.08.09 |
---|---|
현재 페이지를 Ajax 콘텐츠로 바꾸기 (0) | 2023.08.09 |
데이터 프레임의 모든 열에서 데이터 출력(판다) (0) | 2023.08.09 |
MariaDB Prepared 문에서 잘못된 형식의 통신 패킷을 반환합니다. (0) | 2023.08.09 |
.NET의 파일 확장명 및 MIME 유형 (0) | 2023.08.09 |