Home » synchronization

synchronization

asyncio의 동기화수단들

asyncio는 단일 스레드에서 비동기 코루틴을 사용하여 동시성 처리를 한다. 따라서 asyncio의 세계에서는 적어도 멀티 스레드에서 발생할 수 있는 자원 선점문제가 없을 것이라 생각할 수 있다. 전적으로 틀린 것은 아니다. 스레드가 1개밖에 없기 때문에 메모리 내의 특정한 객체를 동시에 액세스하는 일은 없을 것이다. 그러나 그외의 IO와 관련된 자원은 여전히 선점 문제가 발생할 수 있다. 이러한 문제를 피하기 위해서 asyncio는 threading과 유사한 동기화 수단들을 제공하고 있으며, 이들의 사용 방법 또한 거의 유사하다. asyncio에서 제공하는 동기화 수단에는 다음과 같은 것들이 있다.

  • 락(Lock)
  • 이벤트(Event)
  • 컨디션(Condition)
  • 세마포어(Semaphore)
  • 바운디드세마포어(BoundedSemaphore)
더 보기 »asyncio의 동기화수단들

컨디션을 통한 스레드 동기화 예제

동시성을 다룰 때에는 특정한 자원을 동시에 액세스하지 못하도록 관리하거나 여러 작업들이 시작되는 시점을 맞추는 동기화 수단이 필요할 수 있다. Lock은 특정 코드 영역을 동시에 여러 스레드가 실행하지 못하도록 보호할 때 사용하며, 이벤트는 여러 스레드들이 특정 이벤트가 발생할 때까지 기다리다가 동시에 시작될 수 있도록 한다. 컨디션(Condition)은 락과 이벤트가 결합되어 있는 동기화 수단이다.

컨디션은 락을 내재하고 있는 이벤트라 할 수 있다. 락과 마찬가지로 acquire() ~ release() 구간이 있어 한 번에 하나의 스레드/프로세스가 실행되는 영역을 만들 수 있는데, 그 사이에 wait()를 통해서 이벤트를 기다릴 수 있다. 이때 한 스레드가 락을 잠근 상태에서 wait()를 호출하여 이벤트를 기다리게 되면, 같은 컨디션 객체를 점유하고자 하는 스레드가 다시 락을 얻어서 크리티컬 영역에 진입할 수 있다. 이와 같은 방식으로 여러 스레드가 크리티컬 영역에서 이벤트를 기다리는 상태가 될 때, 누군가가 해당 컨디션 이벤트를 set()하게 되면 대기 중인 모든 스레드가 깨어나게 된다. 하지만 이들은 모두 같은 크리티컬 영역에서 대기 중이었기 때문에 일반 이벤트와 달리 한꺼번에 동시에 시작하지 않고, 한 번에 하나씩 크리티컬 영역의 코드를 실행한다. 깨어난 스레드가 락을 릴리즈하는 시점에 wait()를 끝낸 다른 스레드가 실행되는 식으로 순차적으로 크리티컬 구간을 지나게 된다.

더 보기 »컨디션을 통한 스레드 동기화 예제

concurrent.futures를 이용한 병렬처리 예제 – Python

concurrent.futures 를 사용한 병렬처리 멀티스레드로 처리하는 부분은 그냥 동시에 돌린다 뿐이지, 전체적인 수행시간을 줄이는 부분은 아니라서, 여기서는 프로세스 풀을 이용하는 방법을 설명한다. 병렬처리를 위해 작업을 스케줄링하는 부분은 concurrent.futures.ProcessPoolExecutor 클래스의 인스턴스가 담당한다. 사용자는 .submit() 메소드를 이용해서 특정한 동작을 스케줄링하도록 요청하거나, .map() 메소드를 이용해서 입력데이터와 동작함수를 짝지어서 바로 스케줄링할 수 있다. .map() 메소드는 이터레이터를 리턴하는데, 이는 각 개별 작업이 동시에 실행된 후, 먼저 종료된 작업부터 내놓는 리턴값을 내놓게 된다. 보통은 .map 을 이용하면 되는데, Future클래스를 이용하는 방법도 있다. Executor의 .submit() 메소드를 이용하면,… 더 보기 »concurrent.futures를 이용한 병렬처리 예제 – Python