반응형

스레드 간 통신 (Inter-Thread Communication)

프로그램을 실행하는 동안 스레드는 서로 상호 작용해야 하며 이를 스레드 간 통신이라고 합니다. 예를 들어, 생산자-소비자 문제에서 생산자는 품목을 생산한 후 소비자가 소비할 수 있도록 품목이 생산되었음을 소비자에게 알려주어야 합니다.

 

이벤트 객체 사용

스레드 간 통신을 위한 가장 간단한 방법은 이벤트 객체를 사용하는 것입니다. 스레드 중 하나는 신호를 보내고 다른 스레드는 수신을 기다립니다.

 

기본 구문은 다음과 같습니다.

(이벤트 객체 생성) = threading.Event()

 

event_class의 메서드

1. set(): 내부 플래그를 True로 설정하고 대기 중인 모든 스레드가 깨어납니다.

2. clear(): 내부 플래그를 False로 설정하고 대기 중인 모든 스레드는 set()을 호출할 때가지 블록됩니다.

3. isSet(): 지정된 이벤트가 설정되었는지 확인하기 위해 사용합니다.

4. wait() 또는 wait(seconds): 스레드는 이벤트가 설정될 때까지 대기합니다.

 

from threading import *

import time

 

def producer():

    time.sleep(3)

    print("Producer thread producing items:")

    print("Producer thread notification")

    time.sleep(3)

    event.set()

    

def consumer():

    print("Consumer thread waiting")

    event.wait()

    print("Consumer thread consuming items")

    

event = Event()

t1 = Thread(target = producer)

t2 = Thread(target = consumer)

t1.start()

t2.start()

 

Output:

Consumer thread waiting

Producer thread producing items:

Producer thread notification

Consumer thread consuming items

 

Condition 객체 사용

스레드 간 통신을 위한 또 다른 방법은 조건 객체입니다. 조건은 생산자가 품목을 생산하거나 소비자가 품목을 소비하는 등 상태에 변화가 있음을 나타냅니다. 스레드는 해당 조건이 발생할 때까지 기다리며 발생 후 알림을 받습니다. 조건은 잠금과 관련하여 정의됩니다.

 

(조건 객체 생성) = threading.Condition()

 

조건 객체의 메서드

1) acquire(): 조건 객체를 얻는 데 사용됩니다. , 스레드가 내부 잠금을 획득합니다.

2) release(): condition 객체를 해지하기 위해 사용한다. 스레드는 내부 잠금을 해제합니다.

3) wait() 또는 wait(time): 스레드는 알림이나 시간 만료를 받을 때까지 기다립니다.

4) notify(): 대기 중인 스레드 중 하나로 알림이 전송됩니다.

5) notifyAll(): 모든 대기 스레드에 알림이 전송됩니다.

 

다음 스크립트는 Condition 사용법을 보여주고 있습니다. 생산자의 스레드는 리소스에 항목을 생성하고 조건을 획득한 후 소비자에게 신호를 보내기 위해 notify()로 알람을 보냅니다. 반면에 소비자는 조건을 획득한 다음 대기하고 있다가 생산자로부터 알람을 받으면 리소스에서 항목을 소비해야 합니다.

 

from threading import *

import time

 

def producer(c):

    c.acquire()

    print("Producer producing items:")

    print("Producer notification")

    c.notify()

    c.release()

    

def consumer(c):

    c.acquire()

    print("Consumer waiting")

    c.wait()

    print("Consumer notification")

    c.release

    

c = Condition()

t1 = Thread(target = consumer, args = (c,))

t2 = Thread(target = producer, args = (c,))

t1.start()

t2.start()

 

Output:

Consumer waiting

Producer producing items:

Producer notification

Consumer notification

 

Queue 사용

스레드 간 통신을 위한 마지막 방법은 큐를 사용하는 것입니다. 스레드 간 통신에 가장 선호되는 방법입니다. 내부적으로 queue에는 잠금과 관련된 조건이 있습니다. 따라서 queue로 작업하는 동안 동기화에 대해 생각할 필요가 없습니다.

 

사용하는 방법은 다음과 같습니다.

import queue

queue 객체 생성 = queue.Queue()

 

queue 메서드

1)    put() : queue에 항목을 넣습니다.

2)    get() : 항목을 제거하고 quque에서 항목을 반환합니다.

 

다음 스크립트는 queue를 사용한 예제입니다.

생산자 스레드는 put() 메서드를 사용하여 데이터 항목을 queue에 추가합니다.

데이터 항목을 추가하면 잠금이 자동으로 해제됩니다. put() 메소드는 또한 큐가 가득 찼는지 여부를 확인하고 큐가 가득 찼음을 발견하면 생산자 스레드는 wait() 메소드를 호출하여 대기 상태에 들어갈 것입니다. 소비자 스레드는 get() 메서드를 사용하여 큐에서 데이터를 제거하고 가져옵니다. 제거가 완료되면 잠금이 자동으로 해제됩니다. 큐가 비어 있으면 소비자 스레드는 wait() 메서드를 호출하여 대기 상태에 들어갑니다. 큐가 데이터로 업데이트되면 스레드는 자동으로 알림을 받습니다.

 

from threading import *

import time

import random

import queue

 

def producer(q):

    while True:

        item = random.randint(1, 25)

        print("Producer Producting Item: ", item)

        q.put(item)

        print("Producer Notification")

        time.sleep(3)

    

def consumer(q):

    while True:

        print("Consumer waiting ")

        print("Consumer consumed the item:", q.get())

        time.sleep(3)

    

q = queue.Queue()

t1 = Thread(target = consumer, args = (q,))

t2 = Thread(target = producer, args = (q,))

t1.start()

t2.start()

 

Output:

Consumer waiting

Producer Producting Item:  11

Producer Notification

Consumer consumed the item: 11

Consumer waiting

Producer Producting Item:  19

Producer Notification

Consumer consumed the item: 19

Producer Producting Item:  21

Producer Notification

Consumer waiting

Consumer consumed the item: 21

Producer Producting Item:  7Consumer waiting

Producer Notification

…..

 

First-In-First-Out Queue

큐에 처음 삽입된 항목이 대기열에서 가장 먼저 제거됩니다.

 

import queue

 

q = queue.Queue()

q.put(12)

q.put(15)

q.put(22)

while not q.empty():

    print(q.get(), end=' ')

 

Output:

12 15 22

 

Last-In-First-Out Queue

큐에 처음 삽입된 항목이 대기열에서 마지막으로 제거됩니다.

 

import queue

 

q = queue.LifoQueue()

q.put(12)

q.put(15)

q.put(22)

while not q.empty():

    print(q.get(), end=' ')

 

Output:

22 15 12

 

Priority Queue

항목은 할당된 우선 순위에 따라 삽입됩니다.

 

import queue

 

q = queue.PriorityQueue()

q.put(12)

q.put(15)

q.put(22)

while not q.empty():

    print(q.get(), end=' ')

 

Output:

12 15 22

반응형

+ Recent posts