주식 api를 멀티 뜨레드로 이용할 때 데드록이 생기는 경우

멀티 뜨레드로 작동하지 않는 ls증권의 api를 이용하고 있다. 3천 개 정도 종목의 체결과 호가 대이터를 실시간으로 받는다. 수신되는 빈도와 대이터의 양이 너무 많아서 이들을 매인 뜨레드에서 모두 처리하면 하나의 코어에서만 부하가 커져서 멈추게 된다. 패킷을 받은 때 바로 새로운 객체를 만들어 새로운 뜨레드로 보내 연산하면 cpu의 모든 코어들로 부하를 나눌 수 있다.

연산을 한다는 건 그 결과를 사람에게 보이는 게 목적이다. 비주얼 컴포넌트는 매인 뜨래드에서 작동한다. 매인 뜨레드 아닌 뜨레드에서 비주얼 컴포넌트를 수정하려면 invoke를 해야 한다. 이러지 않으면 cross thread exception이 던져진다. 여기까진 특별히 문제될 게 없다.

모든 종목들을 대상으로 한꺼번에 연산을 해야 할 경우가 있다. 예를 들면 분이 바뀌어 전 분 대이터를 연산해야 하는 경우다. 매인 뜨레드 아닌 뜨레드에서 객체가 수정되고 있는데 매인 뜨레드에서도 수정을 시도하면 엉뚱한 대이터가 저장된다. 이 문제를 피하기 위해 각 뜨레드는 lock을 쓴다. 하나의 객체를 두 개 이상의 뜨레드에서 수정하려 하면 락이 걸린 뜨레드들은 순서대로 처리된다.

문제는 이런 경우다.

  1. 매인 뜨레드 아닌 뜨레드가 연산을 하고 있다.
  2. 매인 뜨레드도 마침 1의 뜨레드에서 작동하는 객체를 수정해야 해서 1의 뜨레드가 끝나기를 기다린다.
  3. 1의 뜨레드가 연산을 마치고 invoke를 한다.
  4. 매인 뜨레드는 1의 뜨레드가 끝날 때를 기다리느라 1의 뜨레드가 실행한 invoke를 시작도 못하고 있다.
  5. 1의 뜨레드와 매인 뜨레드 모두 서로가 끝날 때를 기다린다.

deadlock이다.