목차(스레드 / 태스크와 프로세스 / Parallel 클래스)의 멀티스레딩 환경에서 생기는 문제를 lock 키워드로 해결했다.
추가로 lock 키워드에 대해 설명한다.
lock의 중요성
- 데이터 일관성 보장: 여러 스레드가 동시에 데이터를 수정할 때 데이터의 일관성을 보장한다.
- 경쟁 조건 방지: 여러 스레드가 동시에 리소스에 접근하려고 할 때 발생할 수 있는 경쟁 조건을 방지한다.
- 스레드 안전성 제공: 공유 리소스에 대한 안전한 접근을 보장하여 스레드 안전성을 제공한다.
lock 사용 시 주의사항
- 잠금 객체는 참조 타입이어야 한다: lock은 참조 타입의 객체에서만 사용할 수 있다. 값 타입 객체는 사용할 수 없다.
- 잠금 객체는 모든 스레드에서 공유되어야 한다: lock 문에서 사용하는 객체는 모든 관련 스레드가 공유해야 한다. 그렇지 않으면 올바른 동기화가 이루어지지 않는다.
- 잠금 범위를 최소화: lock 블록 내에서 수행하는 작업의 범위를 최소화하여 성능 저하를 방지한다. 불필요한 코드를 lock 블록에 포함하면 병목 현상이 발생할 수 있다.
- 잠금 순환 방지: 여러 잠금 객체를 사용할 때는 잠금 순환(deadlock)을 방지하도록 주의해야 한다. 잠금 순환은 두 개 이상의 스레드가 서로의 잠금을 기다리면서 무한 대기 상태에 빠지는 현상이다.
lock과 관련된 기타 동기화 기법
- Monitor 클래스: Monitor.Enter와 Monitor.Exit 메서드를 사용하여 lock 문과 동일한 기능을 제공한다. Monitor 클래스는 더 많은 기능을 제공하지만, 일반적으로 lock 문이 더 간편하게 사용된다.
- Mutex 클래스: 프로세스 간 동기화에 사용된다. Mutex는 서로 다른 프로세스 간의 동기화가 필요할 때 사용된다.
- Semaphore 클래스: 제한된 리소스에 대한 접근을 제어하는 데 사용된다. 여러 스레드가 동시에 접근할 수 있지만, 제한된 수의 스레드만 접근할 수 있도록 한다.
- ReaderWriterLockSlim 클래스: 읽기 작업이 많은 경우에 유용하다. 여러 스레드가 동시에 읽을 수 있지만, 쓰기 작업이 있을 때는 단일 스레드만 접근할 수 있다.