Thread를 사용하면서 자원공유는 쉬운 문제가 아니다.
예를 들어 txt를 많은 Thread가 동시에 사용한다면 충돌을 피하기 어렵다.
일반적인 파일 입출력 예
using (FileStream Fs = new FileStream(filePath, FileMode.Append))
{
StreamWriter streamWriter = new StreamWriter(Fs, Encoding.UTF8);
streamWriter.Write("Something...\n");
streamWriter.Close();
emailResertFs.Close();
}
Thread가 아니면 문제가 되지 않는 코드이지만 Thread면 문제가 달라진다.
저 코드가 일반적인 상황이 아닌 Thread를 사용하면서 각 Thread가 위의 코드를 처리한다고 가정하자.
운이 좋으면 지나가겠지만 그렇지 않으면 위와 같은 에러를 만나게 된다.
원인은 두개 이상의 Thread가 동시에 txt파일에 액세스 하려고 하면서 발생하는 문제이다.
이 문제를 간단히 해결해보자
해결책 - lock 사용
위의 예제를 이렇게 바꿔보자
private object locker = new object(); //맴버변수로 위에서 따로 정의한다.
lock (locker)
{
using (FileStream Fs = new FileStream(filePath, FileMode.Append))
{
StreamWriter streamWriter = new StreamWriter(Fs, Encoding.UTF8);
streamWriter.Write("Something...\n");
streamWriter.Close();
emailResertFs.Close();
}
}
lock 키워드는 블록 안에 있는 코드를 한 Thread에서만 사용할 수 있게 해주는 키워드이다.
블록에 있는 코드가 끝나기 전까지는 다른 Thread가 들어오지 못한다.
lock()의 파라미터는 임의의 객체를 사용할 수 있지만 일반적으로 private object 형태로 만든다.
Lock(obj)
{
Do Something;
}
특별한 상황이 아니라면 이렇게 만들자.
참고
여기에서 만약에 클래스 객체인 this를 사용하여 lock(this)라고 하면 의도치 않게 데드락이 발생될 수 있기 때문에 this는 사용하지 않는 것이 좋다.
this를 사용하면 집을 잠그는 개념이고 obj를 사용하면 방문을 잠그는 개념.
집을 lock해야 하는 경우도 있기 때문에 무조건 사용하지 않는 것은 아니지만 일반적으로는 방만 lock하자!
마지막으로 코드 블록 ( { } 사이 코드 ) 의 범위는 최대한 작게 하는 것이 좋다.
'Application Language > C#' 카테고리의 다른 글
C# EndsWith() 대소문자 구분 (파일 확장자 대소문자 구분) (0) | 2020.11.10 |
---|---|
C# 문자열 처리 (공백 제거) - Trim() TrimStart() TrimEnd() (0) | 2020.11.09 |