본문 바로가기

python

thread - 동기화(줄서기),lock을 활용한 전역변수 충돌 해결

 

반복문과 thread를 활용한 코드

결과를 보면 알 수 있듯이 thread를 사용하면 번갈아 가며 실행된다. 이때 전역변수를 사용할때 충돌이 일어날 수 있다는 문제가 생긴다. 예시에서도 g_count 전역변수 콘솔 결과를 보면 충돌로 인해  제대로 표기되지 않는 문제가 있다.

# 여러 스레드 간 공유자원 충돌 방지
# 동기화(줄서기) - 하나의 스레드가 자원을 사용하는 동안 다른 스레드는 공유자원사용을 대기

import threading, time

g_count = 0  # 전역변수는 자동으로 스레드의 공유자원이 됨

def threadCount(id, count):
    global g_count
    for i in range(count):
        print('id:%s ===> count:%s, g_count:%s'%(id, i, g_count))
        time.sleep(0.1)
        g_count += 1

for i in range(1, 6):
    threading.Thread(target=threadCount, args=(i, 5)).start()


time.sleep(2)
print('처리 후 최종 g_count : ', g_count)
print('프로그램 종료')

id:1 ===> count:0, g_count:0
id:2 ===> count:0, g_count:0
id:3 ===> count:0, g_count:0
id:4 ===> count:0, g_count:0
id:5 ===> count:0, g_count:0
id:5 ===> count:1, g_count:1id:1 ===> count:1, g_count:2id:3 ===> count:1, g_count:3
id:4 ===> count:1, g_count:4

id:2 ===> count:1, g_count:5

id:2 ===> count:2, g_count:6id:4 ===> count:2, g_count:7

id:5 ===> count:2, g_count:8id:3 ===> count:2, g_count:9

id:1 ===> count:2, g_count:10
id:4 ===> count:3, g_count:11id:3 ===> count:3, g_count:12

id:5 ===> count:3, g_count:13id:1 ===> count:3, g_count:14id:2 ===> count:3, g_count:15


id:3 ===> count:4, g_count:16
id:4 ===> count:4, g_count:17
id:2 ===> count:4, g_count:18
id:1 ===> count:4, g_count:19
id:5 ===> count:4, g_count:20
처리 후 최종 g_count :  25
프로그램 종료

 

 

lock 을 활용한 코드

id 값과 count 값을 보면 반복적으로 thread가 실행되는 것은 확인할 수 있지만 전역변수인 g_count의 충돌은 없어진 것을 확인할 수 있다.

# 여러 스레드 간 공유자원 충돌 방지
# 동기화(줄서기) - 하나의 스레드가 자원을 사용하는 동안 다른 스레드는 공유자원사용을 대기

import threading, time

g_count = 0  # 전역변수는 자동으로 스레드의 공유자원이 됨
lock = threading.Lock()

def threadCount(id, count):
    global g_count
    for i in range(count):
        # thread 간 충돌 방지. 현재 thread가 공유자원을 점유하고 있는 동안 다른 thread를 대기상태로 둔다.
        lock.acquire()
        print('id:%s ===> count:%s, g_count:%s'%(id, i, g_count))
        time.sleep(0.1)
        g_count += 1
        # 공유자원 점유 해제
        lock.release()

for i in range(1, 6):
    threading.Thread(target=threadCount, args=(i, 5)).start()


time.sleep(2)
print('처리 후 최종 g_count : ', g_count)
print('프로그램 종료')

id:1 ===> count:0, g_count:0
id:2 ===> count:0, g_count:1
id:2 ===> count:1, g_count:2
id:2 ===> count:2, g_count:3
id:2 ===> count:3, g_count:4
id:2 ===> count:4, g_count:5
id:3 ===> count:0, g_count:6
id:3 ===> count:1, g_count:7
id:3 ===> count:2, g_count:8
id:3 ===> count:3, g_count:9
id:3 ===> count:4, g_count:10
id:5 ===> count:0, g_count:11
id:5 ===> count:1, g_count:12
id:5 ===> count:2, g_count:13
id:5 ===> count:3, g_count:14
id:5 ===> count:4, g_count:15
id:1 ===> count:1, g_count:16
id:1 ===> count:2, g_count:17
id:1 ===> count:3, g_count:18
처리 후 최종 g_count :  18
프로그램 종료
id:1 ===> count:4, g_count:19
id:4 ===> count:0, g_count:20
id:4 ===> count:1, g_count:21
id:4 ===> count:2, g_count:22
id:4 ===> count:3, g_count:23
id:4 ===> count:4, g_count:24