> 백엔드 개발 > 파이썬 튜토리얼 > Python 프로그래밍에서 스레드 잠금 사용을 설명하는 예

Python 프로그래밍에서 스레드 잠금 사용을 설명하는 예

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
풀어 주다: 2016-08-04 08:55:41
원래의
1446명이 탐색했습니다.

잠금

목록 및 사전과 같은 Python의 내장 데이터 구조는 스레드로부터 안전하지만 정수 및 부동 소수점 숫자와 같은 간단한 데이터 유형은 스레드로부터 안전하지 않습니다. 이러한 간단한 데이터 유형을 작동하려면 잠금을 사용해야 합니다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

#!/usr/bin/env python3

# coding=utf-8

 

import threading

 

shared_resource_with_lock = 0

shared_resource_with_no_lock = 0

COUNT = 100000

shared_resource_lock = threading.Lock()

 

####LOCK MANAGEMENT##

def increment_with_lock():

  global shared_resource_with_lock

  for i in range(COUNT):

    shared_resource_lock.acquire()

    shared_resource_with_lock += 1

    shared_resource_lock.release()

     

def decrement_with_lock():

  global shared_resource_with_lock

  for i in range(COUNT):

    shared_resource_lock.acquire()

    shared_resource_with_lock -= 1

    shared_resource_lock.release()

    ####NO LOCK MANAGEMENT ##

   

def increment_without_lock():

  global shared_resource_with_no_lock

  for i in range(COUNT):

    shared_resource_with_no_lock += 1

   

def decrement_without_lock():

  global shared_resource_with_no_lock

  for i in range(COUNT):

    shared_resource_with_no_lock -= 1

   

####the Main program

if __name__ == "__main__":

  t1 = threading.Thread(target = increment_with_lock)

  t2 = threading.Thread(target = decrement_with_lock)

  t3 = threading.Thread(target = increment_without_lock)

  t4 = threading.Thread(target = decrement_without_lock)

  t1.start()

  t2.start()

  t3.start()

  t4.start()

  t1.join()

  t2.join()

  t3.join()

  t4.join()

  print ("the value of shared variable with lock management is %s"\

  %shared_resource_with_lock)

  print ("the value of shared variable with race condition is %s"\

  %shared_resource_with_no_lock)

로그인 후 복사

실행 결과:

1

$ ./threading_lock.py

로그인 후 복사

1

2

the value of shared variable with lock management is 0

the value of shared variable with race condition is 0

로그인 후 복사

또 다른 예:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

import random

import threading

import time

logging.basicConfig(level=logging.DEBUG,

          format='(%(threadName)-10s) %(message)s',

          )

           

class Counter(object):

  def __init__(self, start=0):

    self.lock = threading.Lock()

    self.value = start

  def increment(self):

    logging.debug(time.ctime(time.time()))

    logging.debug('Waiting for lock')

    self.lock.acquire()

    try:

      pause = random.randint(1,3)

      logging.debug(time.ctime(time.time()))

      logging.debug('Acquired lock')     

      self.value = self.value + 1

      logging.debug('lock {0} seconds'.format(pause))

      time.sleep(pause)

    finally:

      self.lock.release()

def worker(c):

  for i in range(2):

    pause = random.randint(1,3)

    logging.debug(time.ctime(time.time()))

    logging.debug('Sleeping %0.02f', pause)

    time.sleep(pause)

    c.increment()

  logging.debug('Done')

counter = Counter()

for i in range(2):

  t = threading.Thread(target=worker, args=(counter,))

  t.start()

logging.debug('Waiting for worker threads')

main_thread = threading.currentThread()

for t in threading.enumerate():

  if t is not main_thread:

    t.join()

logging.debug('Counter: %d', counter.value)

로그인 후 복사

실행 결과:

1

$ python threading_lock.py

로그인 후 복사

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

(Thread-1 ) Tue Sep 15 15:49:18 2015

(Thread-1 ) Sleeping 3.00

(Thread-2 ) Tue Sep 15 15:49:18 2015

(MainThread) Waiting for worker threads

(Thread-2 ) Sleeping 2.00

(Thread-2 ) Tue Sep 15 15:49:20 2015

(Thread-2 ) Waiting for lock

(Thread-2 ) Tue Sep 15 15:49:20 2015

(Thread-2 ) Acquired lock

(Thread-2 ) lock 2 seconds

(Thread-1 ) Tue Sep 15 15:49:21 2015

(Thread-1 ) Waiting for lock

(Thread-2 ) Tue Sep 15 15:49:22 2015

(Thread-1 ) Tue Sep 15 15:49:22 2015

(Thread-2 ) Sleeping 2.00

(Thread-1 ) Acquired lock

(Thread-1 ) lock 1 seconds

(Thread-1 ) Tue Sep 15 15:49:23 2015

(Thread-1 ) Sleeping 2.00

(Thread-2 ) Tue Sep 15 15:49:24 2015

(Thread-2 ) Waiting for lock

(Thread-2 ) Tue Sep 15 15:49:24 2015

(Thread-2 ) Acquired lock

(Thread-2 ) lock 1 seconds

(Thread-1 ) Tue Sep 15 15:49:25 2015

(Thread-1 ) Waiting for lock

(Thread-1 ) Tue Sep 15 15:49:25 2015

(Thread-1 ) Acquired lock

(Thread-1 ) lock 2 seconds

(Thread-2 ) Done

(Thread-1 ) Done

(MainThread) Counter: 4

로그인 후 복사

acquire()에 False 값을 전달하면 잠금 획득 여부를 확인할 수 있습니다. 예:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

import logging

import threading

import time

logging.basicConfig(level=logging.DEBUG,

          format='(%(threadName)-10s) %(message)s',

          )

           

def lock_holder(lock):

  logging.debug('Starting')

  while True:

    lock.acquire()

    try:

      logging.debug('Holding')

      time.sleep(0.5)

    finally:

      logging.debug('Not holding')

      lock.release()

    time.sleep(0.5)

  return

           

def worker(lock):

  logging.debug('Starting')

  num_tries = 0

  num_acquires = 0

  while num_acquires < 3:

    time.sleep(0.5)

    logging.debug('Trying to acquire')

    have_it = lock.acquire(0)

    try:

      num_tries += 1

      if have_it:

        logging.debug('Iteration %d: Acquired',

               num_tries)

        num_acquires += 1

      else:

        logging.debug('Iteration %d: Not acquired',

               num_tries)

    finally:

      if have_it:

        lock.release()

  logging.debug('Done after %d iterations', num_tries)

lock = threading.Lock()

holder = threading.Thread(target=lock_holder,

             args=(lock,),

             name='LockHolder')

holder.setDaemon(True)

holder.start()

worker = threading.Thread(target=worker,

             args=(lock,),

             name='Worker')

worker.start()

로그인 후 복사

실행 결과:

1

$ python threading_lock_noblock.py

로그인 후 복사

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

(LockHolder) Starting

(LockHolder) Holding

(Worker  ) Starting

(LockHolder) Not holding

(Worker  ) Trying to acquire

(Worker  ) Iteration 1: Acquired

(LockHolder) Holding

(Worker  ) Trying to acquire

(Worker  ) Iteration 2: Not acquired

(LockHolder) Not holding

(Worker  ) Trying to acquire

(Worker  ) Iteration 3: Acquired

(LockHolder) Holding

(Worker  ) Trying to acquire

(Worker  ) Iteration 4: Not acquired

(LockHolder) Not holding

(Worker  ) Trying to acquire

(Worker  ) Iteration 5: Acquired

(Worker  ) Done after 5 iterations

로그인 후 복사

스레드 안전 잠금

1

threading.RLock()

로그인 후 복사

재진입 잠금 객체를 반환합니다. 재진입 잠금은 이를 획득한 스레드에 의해 해제되어야 합니다. 스레드가 재진입 잠금을 획득하면 동일한 스레드가 차단 없이 다시 잠금을 획득할 수 있으며 획득 후에는 해제되어야 합니다.

일반적으로 스레드는 잠금을 한 번만 획득할 수 있습니다.

1

2

3

4

5

6

import threading

 

lock = threading.Lock()

 

print 'First try :', lock.acquire()

print 'Second try:', lock.acquire(0)

로그인 후 복사

실행 결과:

1

$ python threading_lock_reacquire.py

로그인 후 복사

1

2

First try : True

Second try: False

로그인 후 복사

RLock을 사용하여 여러 잠금을 얻으세요:

1

2

3

4

import threading

lock = threading.RLock()

print 'First try :', lock.acquire()

print 'Second try:', lock.acquire(0)

로그인 후 복사

실행 결과:

1

python threading_rlock.py

로그인 후 복사

1

2

First try : True

Second try: 1

로그인 후 복사

또 다른 예를 살펴보겠습니다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

#!/usr/bin/env python3

# coding=utf-8

import threading

import time

class Box(object):

  lock = threading.RLock()

  def __init__(self):

    self.total_items = 0

  def execute(self,n):

    Box.lock.acquire()

    self.total_items += n

    Box.lock.release()

  def add(self):

    Box.lock.acquire()

    self.execute(1)

    Box.lock.release()

  def remove(self):

    Box.lock.acquire()

    self.execute(-1)

    Box.lock.release()

     

## These two functions run n in separate

## threads and call the Box's methods   

def adder(box,items):

  while items > 0:

    print ("adding 1 item in the box\n")

    box.add()

    time.sleep(5)

    items -= 1

     

def remover(box,items):

  while items > 0:

    print ("removing 1 item in the box")

    box.remove()

    time.sleep(5)

    items -= 1

     

## the main program build some

## threads and make sure it works

if __name__ == "__main__":

  items = 5

  print ("putting %s items in the box " % items)

  box = Box()

  t1 = threading.Thread(target=adder,args=(box,items))

  t2 = threading.Thread(target=remover,args=(box,items))

  t1.start()

  t2.start()

  t1.join()

  t2.join()

  print ("%s items still remain in the box " % box.total_items)

로그인 후 복사

실행 결과:

1

$ python3 threading_rlock2.py

로그인 후 복사

1

2

3

4

5

6

7

8

9

10

11

12

putting 5 items in the box

adding 1 item in the box

removing 1 item in the box

adding 1 item in the box

removing 1 item in the box

adding 1 item in the box

removing 1 item in the box

removing 1 item in the box

adding 1 item in the box

removing 1 item in the box

adding 1 item in the box

0 items still remain in the box

로그인 후 복사
관련 라벨:
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿