MonitorMixin

MonitorMixin

동시성 프로그래밍에서 모니터(monitor)는 둘 이상의 스레드가 안전하게 사용하도록 만들어진 객체나 모듈이에요. 모니터를 규정하는 핵심 특징은, 그 메서드들이 상호 배제로 실행된다는 거예요. 즉 어느 시점에서도 최대 한 개의 스레드만 그 메서드 중 하나를 실행할 수 있어요. 이런 상호 배제 덕분에, 데이터 구조를 갱신하는 병렬 코드를 생각하는 것보다 모니터 구현을 훨씬 단순하게 추론할 수 있어요.

출처: Ruby 3.3 API

본문

모니터의 일반적인 원리는 Wikipedia의 Monitors 문서에서 더 자세히 볼 수 있어요.

Examples

Simple object.extend

require 'monitor.rb'

buf = []
buf.extend(MonitorMixin)
empty_cond = buf.new_cond

# consumer
Thread.start do
  loop do
    buf.synchronize do
      empty_cond.wait_while { buf.empty? }
      print buf.shift
    end
  end
end

# producer
while line = ARGF.gets
  buf.synchronize do
    buf.push(line)
    empty_cond.signal
  end
end

소비자 스레드는 buf.empty? 동안 생산자 스레드가 buf에 한 줄을 넣기를 기다려요. 생산자 스레드(메인 스레드)는 ARGF에서 한 줄을 읽어 buf에 넣은 뒤, empty_cond.signal을 호출해서 새 데이터가 있음을 소비자 스레드에 알려줘요.

Simple Class include

require 'monitor'

class SynchronizedArray < Array

  include MonitorMixin

  def initialize(*args)
    super(*args)
  end

  alias :old_shift :shift
  alias :old_unshift :unshift

  def shift(n=1)
    self.synchronize do
      self.old_shift(n)
    end
  end

  def unshift(item)
    self.synchronize do
      self.old_unshift(item)
    end
  end

  # other methods ...
end

SynchronizedArray는 항목에 대한 동기화된 접근을 구현한 Array예요. 이 클래스는 MonitorMixin 모듈을 include한 Array의 하위 클래스로 구현돼요.

Public Class Methods

extend_object(obj)

슈퍼클래스 메서드를 호출해요.

new(...)

이 생성자 대신 extend MonitorMixin이나 include MonitorMixin을 사용하세요. 이 모듈을 어떻게 쓰는지는 위 예시들을 보면 이해할 수 있어요. (슈퍼클래스 메서드를 호출해요.)

Public Instance Methods

mon_enter()

배타 구역(exclusive section)에 들어가요.

mon_exit()

배타 구역에서 나와요.

mon_locked?()

이 모니터가 어떤 스레드에 의해 잠겨 있으면 true를 돌려줘요.

mon_owned?()

이 모니터가 현재 스레드에 의해 잠겨 있으면 true를 돌려줘요.

mon_synchronize(&b)

배타 구역에 들어가 블록을 실행하고, 블록이 끝나면 자동으로 배타 구역에서 나와요. MonitorMixin 아래의 예시를 참고하세요. (synchronize로도 별칭돼 있어요.)

mon_try_enter()

배타 구역 진입을 시도해요. 잠금에 실패하면 false를 돌려줘요. (try_mon_enter로도 별칭돼 있어요.)

new_cond()

Monitor 객체에 연결된 새 MonitorMixin::ConditionVariable을 만들어요.

synchronize(&b)

mon_synchronize의 별칭이에요.

try_mon_enter()

하위 호환성을 위해 있는 메서드예요. mon_try_enter의 별칭이에요.

Private Instance Methods

mon_check_owner()

mon_initialize()

클래스에 include되거나 객체가 MonitorMixin으로 extend된 뒤 MonitorMixin을 초기화해요.

더 알아보기

  • 모니터를 직접 쓸 수 있게 만든 Monitor 클래스 문서도 함께 보세요.