인자로는 hEvent : PyHANDLE, lReleaseCount : int 가 있습니다.
hEvent는 세마포어의 핸들 값입니다.
lReleaseCount는 세마포어 점유 해제 시 카운트를 몇을 증가시킬 지 정합니다. 기본적으로 1로 설정하는 듯 합니다.
- WaitForSingleObject로 세마포어를 점유 시 세마포어의 카운트가 1씩 감소합니다. 현재 예제에서는 최대 카운트가 2, 초기 카운트가 1이였으니 WaitForSingleObject을 한번 호출하면 세마포어의 카운트가 0이 되면서 다른 쓰레드가 접근을 하지 못하게 됩니다.
return 값은 세마포어를 점유 해제하기 전 세마포어의 카운트 값입니다.
import threading
import win32event
import win32con
import win32api
total=0
sHandle=0
def sum(num):
global total
global sHandle
win32event.WaitForSingleObject(sHandle, win32event.INFINITE)
for i in range(100000):
total+=1
pCnt = win32event.ReleaseSemaphore(sHandle, 1)
print(f"Subthread {num} : {total}\n")
x = win32event.CreateSemaphore(None, 1, 2, "semaTest")
sHandle=win32event.OpenSemaphore(win32event.EVENT_ALL_ACCESS, win32con.FALSE, "semaTest")
t = threading.Thread(target=sum, args=(1,))
t2 = threading.Thread(target=sum, args=(2,))
t.start()
t2.start()
print("Main Thread\n")
win32api.CloseHandle(sHandle)
win32api.CloseHandle(x)
위의 예제는 Mutex 예제와 동일하게 동작합니다. 하지만, x = win32event.CreateSemaphore(None, 1, 2, "semaTest") 이 부분을 x = win32event.CreateSemaphore(None, 2, 2, "semaTest")로 바꿔서 실행시켜 보시면, 쓰레드 2개가 동시에 total 변수에 접근이 가능해져서 계산 결과가 이상하게 나오게 됩니다.
x = win32event.CreateSemaphore(None, 1, 2, "semaTest")인 경우
x = win32event.CreateSemaphore(None, 2, 2, "semaTest")인 경우
import threading
import win32event
import win32con
import win32api
total=0
mHandle=0
def sum(num):
global total
global mHandle
win32event.WaitForSingleObject(mHandle, win32event.INFINITE)
# 여기와
for i in range(100000):
total+=1
win32event.ReleaseMutex(mHandle)
# 여기를 지우고 실행시키면 결과가 달라집니다.
print(f"Subthread {num} : {total}\n")
x = win32event.CreateMutex(None, win32con.FALSE, "mutexTest")
# win32event.ReleaseMutex(x)
mHandle=win32event.OpenMutex(win32event.SYNCHRONIZE, win32con.FALSE, "mutexTest")
t = threading.Thread(target=sum, args=(1,))
t2 = threading.Thread(target=sum, args=(2,))
t.start()
t2.start()
print("Main Thread\n")
win32api.CloseHandle(mHandle)
win32api.CloseHandle(x)
갑자기 코드가 늘어났습니다.ㅎㅎ
먼저 threading 모듈은 파이썬에서 쓰레드를 생성시켜주는 모듈입니다. 뮤텍스의 사용에 대한 설명을 하기 위해서는 쓰레드가 필요해서 넣었습니다.
간단히 설명하자면, 두개의 쓰레드가 total이라는 하나의 변수에 값을 1씩 계속 더하는 코드입니다. 문제는 두개의 쓰레드가 total 변수에 동시에 접근할 떄 값이 제대로 더해지지 않는 경우가 생긴다는 겁니다. 이런 경우를 위해서 뮤텍스를 이용해 쓰레드의 동시 접근을 막고 하나만 접근할 수 있게 합니다.
위의 결과가 뮤텍스를 이용했기 때문에 제대로 total이 증가한 상황입니다.
만약 코드에서 표시한 부분(뮤텍스 부분)을 주석처리한 후 실행한다면 위처럼 total이 제대로 증가하지 않을 것입니다.