주식 api를 멀티 뜨레드로 이용할 때 데드록이 생기는 경우
멀티 뜨레드로 작동하지 않는 ls증권의 api를 이용하고 있다. 3천 개 정도 종목의 체결과 호가 대이터를 실시간으로 받는다. 수신되는 빈도와 대이터의 양이 너무 많아서 이들을 매인 뜨레드에서 모두 처리하면 하나의 코어에서만 부하가 커져서 멈추게 된다. 패킷을 받은 때 바로 새로운 객체를 만들어 새로운 뜨레드로 보내 연산하면 cpu의 모든 코어들로 부하를 나눌 수 있다.
연산을 한다는 건 그 결과를 사람에게 보이는 게 목적이다. 비주얼 컴포넌트는 매인 뜨래드에서 작동한다. 매인 뜨레드 아닌 뜨레드에서 비주얼 컴포넌트를 수정하려면 invoke를 해야 한다. 이러지 않으면 cross thread exception이 던져진다. 여기까진 특별히 문제될 게 없다.
모든 종목들을 대상으로 한꺼번에 연산을 해야 할 경우가 있다. 예를 들면 분이 바뀌어 전 분 대이터를 연산해야 하는 경우다. 매인 뜨레드 아닌 뜨레드에서 객체가 수정되고 있는데 매인 뜨레드에서도 수정을 시도하면 엉뚱한 대이터가 저장된다. 이 문제를 피하기 위해 각 뜨레드는 lock을 쓴다. 하나의 객체를 두 개 이상의 뜨레드에서 수정하려 하면 락이 걸린 뜨레드들은 순서대로 처리된다.
문제는 이런 경우다.
- 매인 뜨레드 아닌 뜨레드가 연산을 하고 있다.
- 매인 뜨레드도 마침 1의 뜨레드에서 작동하는 객체를 수정해야 해서 1의 뜨레드가 끝나기를 기다린다.
- 1의 뜨레드가 연산을 마치고 invoke를 한다.
- 매인 뜨레드는 1의 뜨레드가 끝날 때를 기다리느라 1의 뜨레드가 실행한 invoke를 시작도 못하고 있다.
- 1의 뜨레드와 매인 뜨레드 모두 서로가 끝날 때를 기다린다.
deadlock이다.