채널과 동시성
채널과 동시성
섹션 제목: “채널과 동시성”프로세스 내 동시 프로그래밍을 위한 Go 스타일 채널.
채널 생성
섹션 제목: “채널 생성”채널은 코루틴 간 통신 파이프입니다. channel.new(capacity)로 생성합니다:
local ch = channel.new(1) -- 버퍼드 채널, 용량 1버퍼드 채널
섹션 제목: “버퍼드 채널”버퍼드 채널은 버퍼가 가득 찰 때까지 블로킹 없이 전송을 허용합니다:
local ch = channel.new(3) -- 버퍼가 3개 항목 보유
-- 블로킹 없이 전송ch:send(1)ch:send(2)ch:send(3)
-- FIFO 순서로 수신local v1, ok1 = ch:receive() -- 1, truelocal v2, ok2 = ch:receive() -- 2, truelocal v3, ok3 = ch:receive() -- 3, true언버퍼드 채널
섹션 제목: “언버퍼드 채널”언버퍼드 채널(용량 0)은 송신자와 수신자를 동기화합니다:
local ch = channel.new(0) -- 언버퍼드local done = channel.new(1)
coroutine.spawn(function() ch:send("from spawn") -- 수신자 준비될 때까지 블록 done:send(true)end)
local val = ch:receive() -- "from spawn" 수신local completed = done:receive()채널 Select
섹션 제목: “채널 Select”channel.select는 여러 채널에서 대기하고 첫 번째 준비된 작업을 반환합니다:
local ch1 = channel.new(1)local ch2 = channel.new(1)
ch1:send("ch1_value")
local result = channel.select{ ch1:case_receive(), ch2:case_receive()}
-- result는 channel, value, ok를 가진 테이블result.channel == ch1 -- trueresult.value -- "ch1_value"result.ok -- trueSend를 포함한 Select
섹션 제목: “Send를 포함한 Select”case_send를 사용하여 논블로킹 전송을 시도합니다:
local ch = channel.new(1)
local result = channel.select{ ch:case_send("sent")}
result.ok -- true (전송 성공)
local v = ch:receive() -- "sent"생산자-소비자 패턴
섹션 제목: “생산자-소비자 패턴”단일 생산자, 단일 소비자:
local ch = channel.new(5)local done = channel.new(1)local consumed = 0
-- 소비자coroutine.spawn(function() while true do local v, ok = ch:receive() if not ok then break end consumed = consumed + 1 end done:send(consumed)end)
-- 생산자for i = 1, 10 do ch:send(i)endch:close()
local total = done:receive() -- 10핑퐁 패턴
섹션 제목: “핑퐁 패턴”두 코루틴을 동기화합니다:
local ping = channel.new(0)local pong = channel.new(0)local rounds_done = channel.new(1)
coroutine.spawn(function() for i = 1, 5 do ping:receive() pong:send("pong") end rounds_done:send(true)end)
for i = 1, 5 do ping:send("ping") pong:receive()end
local completed = rounds_done:receive()Fan-Out 패턴
섹션 제목: “Fan-Out 패턴”하나의 생산자, 여러 소비자:
local work = channel.new(10)local results = channel.new(10)
-- 3개의 워커 스폰for w = 1, 3 do coroutine.spawn(function() while true do local job, ok = work:receive() if not ok then break end results:send(job * 2) end end)end
-- 작업 전송for i = 1, 6 do work:send(i)endwork:close()
-- 결과 수집local sum = 0for i = 1, 6 do local r = results:receive() sum = sum + rend-- sum = (1+2+3+4+5+6)*2 = 42Fan-In 패턴
섹션 제목: “Fan-In 패턴”여러 생산자, 단일 소비자:
local output = channel.new(10)local producer_count = 4local items_per_producer = 5
-- 생산자 스폰for p = 1, producer_count do coroutine.spawn(function() for i = 1, items_per_producer do output:send({producer = p, item = i}) end end)end
-- 모든 메시지 수집local received = {}for i = 1, producer_count * items_per_producer do local msg = output:receive() table.insert(received, msg)end
-- 모든 생산자가 항목을 보냈는지 확인local counts = {}for _, msg in ipairs(received) do counts[msg.producer] = (counts[msg.producer] or 0) + 1end채널 닫기
섹션 제목: “채널 닫기”완료를 알리기 위해 채널을 닫습니다. 수신자는 채널이 닫히고 비어있을 때 ok = false를 받습니다:
local ch = channel.new(5)local done = channel.new(1)
coroutine.spawn(function() local count = 0 while true do local v, ok = ch:receive() if not ok then break end -- 채널 닫힘 count = count + 1 end done:send(count)end)
for i = 1, 10 do ch:send(i)endch:close() -- 더 이상 값이 없음을 알림
local total = done:receive()채널 메서드
섹션 제목: “채널 메서드”사용 가능한 작업:
channel.new(capacity)- 버퍼 크기로 채널 생성ch:send(value)- 값 전송 (버퍼가 가득 차면 블록)ch:receive()- 값 수신,value, ok반환ch:close()- 채널 닫기ch:case_send(value)- select를 위한 전송 케이스 생성ch:case_receive()- select를 위한 수신 케이스 생성channel.select{cases...}- 여러 작업에서 대기