동시성
12편
취소는 부탁이지 명령이 아니다
스레드를 강제로 죽이는 방법은 없습니다. 대신 "이제 그만해 주세요" 를 전달하고 받는 쪽이 협조합니다.
자물쇠가 없어도 데드락은 걸린다
화면이 얼어붙었는데 예외도 로그도 없습니다. lock 은 한 줄도 없습니다. .Result 한 줄이면 충분합니다.
await 는 기다림을 넘길 뿐 일을 넘기지 않는다
무거운 계산에 async 를 붙였는데 화면이 그대로 멈춥니다. 안에 await 를 하나 넣어도 마찬가지입니다. 재보면 이유가 보입니다.
async 는 스레드를 만들지 않는다
스레드가 여럿일 때 생기는 문제와 async 는 다른 이야기입니다.
끝이 없는 큐는 메모리가 대신 끝을 낸다
넣는 쪽이 꺼내는 쪽보다 빠르면 큐가 자랍니다. 상한을 안 정하면 남은 메모리가 상한이 됩니다.
소켓에 둘이 동시에 쓰면 프레임이 섞인다
자물쇠로 못 막는 자리가 있습니다. 기다리게 하는 대신 줄을 세워 한 명만 쓰게 만듭니다.
false sharing 은 공유한 적이 없어서 false 다
스레드마다 자기 카운터를 줬는데 병렬화가 오히려 느려집니다. 락도 없고 겹쳐 쓴 값도 없습니다. 두 카운터가 같은 64바이트 캐시 라인에 앉아 있어서 그렇습니다. false sharing 이 무엇이고 어떻게 확인하고 어떻게 고치는지를 직접 재본 숫자로 봅니다.
한 스레드만 만지면 잠글 것이 없다
자물쇠는 부딪혔을 때 처리하는 도구입니다. 애초에 안 부딪히게 짜면 자물쇠가 필요 없습니다.
내가 처음인지 물어보려면 CompareExchange 다
lock 은 들어가도 되는지만 알려 줍니다. 딱 한 번만 일어나야 하는 일에는 다른 도구가 필요합니다.
조건 변수는 락을 놓고 기다렸다가 다시 잡는다
락을 쥔 채로 조건을 기다리면 아무도 그 조건을 바꿔 줄 수 없습니다. 조건 변수는 락을 놓는 것과 기다리는 것을 한 번에 합니다. Monitor.Wait 과 Pulse 가 그것이고, if 로 검사하면 100번 중 100번 깨집니다.
lock 은 순서를 만들고 대가를 받는다
여러 줄을 묶어 지키는 유일한 방법인데, 걸어 놓고 잘못 쓰면 프로그램이 멈춰 섭니다.
count++ 는 한 번에 일어나지 않는다
한 줄짜리 코드가 기계에서는 세 걸음입니다. 그 사이에 남이 끼어들면 더한 값이 사라집니다.