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클래스 문서도 함께 보세요.