본문 바로가기

python

thread - lock (빵 공장 예제)

 

lock을 사용하기 전 코드

공유 자원이 심하게 충돌하는 것을 확인할 수 있다.

# thread 간의 자원공유 + thread 활성화/비활성화

import threading, time

# 빵접시 - 공유자원
bread_plate = 0  
lock = threading.Condition()

# 빵 생산자
# thread 상속
class Maker(threading.Thread):
    def run(self):
        global bread_plate
        for i in range(3):
            bread_plate += 1
            print('빵생산 : ',bread_plate)
            time.sleep(0.05)
            
# 빵 소비자
class Consumer(threading.Thread):
    def run(self):
        global bread_plate
        for i in range(3):
            bread_plate -= 1
            print('빵소비 : ',bread_plate)
            time.sleep(0.05)

mak = []; con = []
# 생산자 수
for i in range(5):
    mak.append(Maker())
    
# 소비자 수
for i in range(5):
    con.append(Consumer())

for th1 in mak:
    th1.start()
    
for th2 in con:
    th2.start()
    
for th1 in mak:
    th1.join()
    
for th2 in con:
    th2.join()
    
print('오늘 영업 끝~~~')

빵생산 :  1
빵생산 :  2
빵생산 :  3
빵생산 :  4
빵생산 :  5
빵소비 :  4
빵소비 :  3
빵소비 :  2
빵소비 :  1
빵소비 :  0
빵소비 : 빵소비 : 빵생산 : 빵소비 : 빵생산 :   빵소비 : -3  -1빵소비 : -1 빵생산 : 
빵생산 :  
-2
빵생산 :   -2-2

  -2
0-3

-1

빵소비 : 빵소비 :   빵생산 : -1빵소비 : 
 -1빵생산 : 
  -10
0
빵소비 :  -1
빵생산 : 빵생산 :  
빵소비 :   빵생산 : -10
 
00

오늘 영업 끝~~~

 

 

lock을 조건을 붙여 사용한 코드

lock.acquire(), lock.release() 를 활용하여 공유자원이 충돌되지 않게 하였다.

lock.wait(), lock.notify() 를 활용하여 특정 상황에서 thread를 잠시 비활성화하게 하였다. 예시에서는 빵이 3개 이상일 때 생산 일시정지와 빵이 1개 미만일때 (빵이 없을 때)  소비 일시정지 기능을 넣었다.

# thread 간의 자원공유 + thread 활성화/비활성화

import threading, time

# 빵접시 - 공유자원
bread_plate = 0  
lock = threading.Condition()

# 빵 생산자
# thread 상속
class Maker(threading.Thread):
    def run(self):
        global bread_plate
        for i in range(3):
            lock.acquire()     # 공유자원 점유
            while bread_plate >= 3:
                print('빵 생산 초과로 대기')
                lock.wait()    # thread 비활성화
            bread_plate += 1
            print('빵생산 : ',bread_plate)
            lock.notify()      # thread 활성화
            lock.release()     # 공유자원 점유 해제
            time.sleep(0.05)
            
# 빵 소비자
class Consumer(threading.Thread):
    def run(self):
        global bread_plate
        for i in range(3):
            lock.acquire()     # 공유자원 점유
            while bread_plate < 1:
                print('빵 소비 초과로 대기')
                lock.wait()    # thread 비활성화
            bread_plate -= 1
            print('빵소비 : ',bread_plate)
            lock.notify()      # thread 활성화
            lock.release()     # 공유자원 점유 해제
            time.sleep(0.05)

mak = []; con = []
# 생산자 수
for i in range(5):
    mak.append(Maker())
    
# 소비자 수
for i in range(5):
    con.append(Consumer())

for th1 in mak:
    th1.start()
    
for th2 in con:
    th2.start()
    
for th1 in mak:
    th1.join()
    
for th2 in con:
    th2.join()
    
print('오늘 영업 끝~~~')

빵생산 :  1
빵생산 :  2
빵생산 :  3
빵 생산 초과로 대기
빵 생산 초과로 대기
빵소비 :  2
빵소비 :  1
빵생산 :  2
빵소비 :  1
빵생산 :  2
빵소비 :  1
빵소비 :  0
빵생산 :  1
빵소비 :  0
빵 소비 초과로 대기
빵생산 :  1
빵소비 :  0
빵생산 :  1
빵생산 :  2
빵생산 :  3
빵소비 :  2
빵소비 :  1
빵소비 :  0
빵생산 :  1
빵소비 :  0
빵 소비 초과로 대기
빵생산 :  1
빵소비 :  0
빵생산 :  1
빵소비 :  0
빵생산 :  1
빵소비 :  0
빵생산 :  1
빵소비 :  0
오늘 영업 끝~~~