lock 클래스는 임의로 만든 lock 클래스이고 실제 중요한것은 AutoResetEvent 이다
초기 AutoResetEvent 값은 true 였고, 초기 값을 false 로 설정 하는것도 가능하다
waitOne() 함수를 만나 상태가 false 가 되면서 락을 소유하게 된다, 그래서 다른 스레드는 더이상 접근하게 못하게 되다가
.Set() 을 하는 순간 AutoResetEvent 가 다시 true 상태가 됨으로 이후 부턴 다른 스레드도
waitOne 에서 락을 획득하여 들어올 수 있게 된다
AutoResetEvent 는 waitOne 에 진입함과 동시에 자신의 상태를 false 로 만든다는 특징이 있다
이렇게 코드를 돌릴때 한쪽에서만 공유변수 _num 을 증가 또는 감소 할 수 있게 된다
ManualResetEvent
이건 문을 자동으로 닫진 않는다 즉 waitOne 에서 lock 을 획득하면 자도으로 ManualResetEvent 상태를 false 로 만들지 않는다는 것이고 이것을 수기로 해줘야 한다
ManualResetEvent.Reset(); false 로 바꾸는 함수
이렇게 하면 문제가 발생하는데
reset 과 watiOne 사이에 여러 스레드가 동시에 들어올 수 있기 때문에 정확한 처리가 되지 않는다
하지만 의도가 여러 스레드의 입장이 동시에 가능하게 할 것이라면 이 처리는 맞게 된다
ex ManualResetEvet 를 댐 같은것이라 생각하면 예시가 될 수 있는데
사용자가 게임 진입 버튼을 누르기 전까지 ManualResetEvet 에 의해 모든 스레드가 대기 하고 있다가
버튼 을 누르면 인터넷으로부터 데이터를 받아오거나 로컬 파일을 동시에 읽는다던가 맵을 이동하는 등
여러 스레드들을 버튼 누른 시점 이후부터 동작하게 하기위한 스레드 대기의 용도로 사용 할 수 도 있다
spinlock 은 유저모드에서 실행되는거라 cpu 타임만 갉아 먹는데
AutoResetEvent, ManualResetEvent 은 커널모드에서 돌아가는 것이기 때문에 context switch 가 일어나게 되어 성능이 유저모드에 비해 떨어 질 수가 있다
커널모드 동기화 중에 다른 것이 Mutex 가 있다
위의 WiatOne(문을 잠금) 으로 lock 을 소유하고 ReleaseMutex(문을 다시 연다) 를 통해서 mutex 의 lock 을 놓아준다
mutex 와 autoResetEvent 의 차이는
Mutex 는 lock을 잡을떄 카운팅을 할 수 있고 mutex 는 스레드 id 또한 갖고 있어서
문제가 있을때 유용한데 추가 비용이 좀 더 들어간다
'프로그래밍(Programming) > C#' 카테고리의 다른 글
ReaderWriterLockSlim (0) | 2022.11.27 |
---|---|
SpinLock (0) | 2022.11.27 |
컨텍스트 스위칭을 발생시키는 명령 Thread.Sleep 0 , 1 , yield (0) | 2022.11.27 |
Interlocked.CompareExchange(ref _lockecd, desired, expected) (0) | 2022.11.27 |
Deadlock 현상 (0) | 2022.11.27 |