인프런 강의 를 듣고, 개인 공부 목적으로 정리한 글입니다.
Read는 많이 하는데 Write의 빈도가 너무 작아서,,
매번 Mutex를 하기엔 부담인 경우도 있다.
그럴 때 ReadWriteLock을 사용하면 좋겠다.
뭐냐면
WriteLock이 없으면 Read는 동시다발적으로 접근할 수 있다.
단, WriteLock이 있다면 Read 불가.
즉,
ReadLock
은 여러 번 불릴 수 있다.
단, WriteLock -> ReadLock
= X
여기서 만약 재귀적 Lock을 허용한다면
WriteLock -> WriteLock
: OK
WriteLock -> ReadLock
: OK
ReadLock -> WriteLock
: X
이론은 이렇다.
32bit int 자료형으로 flag
변수를 이용한다.
[Unused(0)]
[WriteThreadID(15)]
[ReadCount(16)]
Unused
: 최상위 비트는 음수가 될 가능성이 있으니 사용하지 않고,
WriteThreadID
: WriteLock을 건 쓰레드의 ID
(재귀적 Lock을 허용할 경우 누가 Write를 잡고 있는지 확인해야 함)
ReadCount
: ReadLock에 접근한 쓰레드의 개수
5000번 spin하고 안되면 Yield한다 (spinlock)
재귀적 lock을 허용한다는 가정.
만약 WriteThreadID
가 현재 쓰레드 ID라면 WriteCount를 늘리고 리턴 (재귀적 락)
아니라면,
WriteThreadID
가 0임을 확인한다.
만약 flag
의 WriteThreadID
가 0이라면 writeCount
를 1로 만들고 리턴
writeCount
가 0이라면 flag
를 0으로 싹 밀어준다.
(WritLock하면 ReadLock도 접근 불가능하므로)
만약 WriteCount가 0이 아니라면 --WriteCount하면 됨
만약 WriteThreadID
가 현재 쓰레드 ID라면 flag
를 늘리고 리턴 (재귀적 락)
만약 flag
의 WriteThreadID
가 0이라면 ReadCount
를 1 늘려준다.
flag
를 1 줄여준다.
88
88 << 3
704 >> 2
const int EMPTY_FLAG = 0x00000000;
const int WRITE_MASK = 0x7FFF0000;
const int READ_MASK = 0x0000FFFF;
앞서 말했듯,
이렇게 된다고 쳤을 때
WriteThreadID
에 대한 값을 위해
WRITE_MASK
는 상위 15개의 비트에 대해, 나머지는 다 0이어야 한다
이렇게 정해줘야
다른 값들과 AND 연산해서 비교할 수 있다.
그래서 WRITE_MASK
는 0x7FFFF0000
READ_MASK
도 동일한 방식이다.