【Python@Thread】锁示例

  当出现竞态条件时候,即在同一个时刻只有一个线程可以进入临界区,需要使用同步。

常见的同步原语有两种:锁/互斥,信号量。

  锁是最简单,最低级的机制。

首先看一个不使用锁时候的多线程示例:

from atexit import register
from time import sleep, ctime
from threading import currentThread, Thread
from random import randrange


class cleanOutput(list):
    def __str__(self):
        return ','.join(self)

loops = [randrange(2, 5) for x in range(randrange(3, 7))]
remaining = cleanOutput()


def loop(nsec):
    myname = currentThread().name
    remaining.append(myname)
    print('{0} starting at {1}'.format(myname, ctime()))
    sleep(nsec)
    remaining.remove(myname)
    print('{0} end at {1}'.format(myname, ctime()))
    print('remaining {0}'.format(remaining))


def main():
    for i in loops:
        Thread(target=loop, args=(i,)).start()


@register
def _atexit():
    print("end!")


if __name__ == '__main__':
    main()

输出结果1:

Thread-1 starting at Tue Dec 20 23:12:03 2016
Thread-2 starting at Tue Dec 20 23:12:03 2016
Thread-3 starting at Tue Dec 20 23:12:03 2016
Thread-4 starting at Tue Dec 20 23:12:03 2016
Thread-5 starting at Tue Dec 20 23:12:03 2016
Thread-6 starting at Tue Dec 20 23:12:03 2016
Thread-2 end at Tue Dec 20 23:12:05 2016
Thread-3 end at Tue Dec 20 23:12:05 2016
Thread-5 end at Tue Dec 20 23:12:05 2016
remaining Thread-1,Thread-4,Thread-6
remaining Thread-1,Thread-4,Thread-6
remaining Thread-1,Thread-4,Thread-6
Thread-1 end at Tue Dec 20 23:12:06 2016
remaining Thread-4,Thread-6
Thread-6 end at Tue Dec 20 23:12:06 2016
remaining Thread-4
Thread-4 end at Tue Dec 20 23:12:06 2016
remaining
end!

输出结果2:

Thread-1 starting at Tue Dec 20 23:18:45 2016
Thread-2 starting at Tue Dec 20 23:18:45 2016
Thread-3 starting at Tue Dec 20 23:18:45 2016
Thread-4 starting at Tue Dec 20 23:18:45 2016
Thread-1 end at Tue Dec 20 23:18:47 2016
remaining Thread-2,Thread-3,Thread-4
Thread-3 end at Tue Dec 20 23:18:47 2016
Thread-2 end at Tue Dec 20 23:18:47 2016
remaining Thread-4
remaining Thread-4
Thread-4 end at Tue Dec 20 23:18:48 2016
remaining
end!

可以看到输出的结果非常奇怪,当多个线程同时使用remaining列表时候,结果会出现意外。

当使用锁时,即

 1 from atexit import register
 2 from time import sleep, ctime
 3 from threading import currentThread, Thread, Lock
 4 from random import randrange
 5 
 6 
 7 class cleanOutput(list):
 8     def __str__(self):
 9         return ','.join(self)
10 
11 loops = [randrange(2, 5) for x in range(randrange(3, 7))]
12 remaining = cleanOutput()
13 lock = Lock()
14 
15 
16 def loop(nsec):
17     myname = currentThread().name
18     with lock:          #也可以使用lock.acquire()和lock.release()
19         remaining.append(myname)          
20         print('{0} starting at {1}'.format(myname, ctime()))
21     sleep(nsec)
22     with lock:
23         remaining.remove(myname)
24         print('{0} end at {1}'.format(myname, ctime()))
25         print('remaining {0}'.format(remaining))
26 
27 
28 def main():
29     for i in loops:
30         Thread(target=loop, args=(i,)).start()
31 
32 
33 @register
34 def _atexit():
35     print("end!")
36 
37 
38 if __name__ == '__main__':
39     main()

输出结果为:

Thread-1 starting at Tue Dec 20 23:22:53 2016
Thread-2 starting at Tue Dec 20 23:22:53 2016
Thread-3 starting at Tue Dec 20 23:22:53 2016
Thread-4 starting at Tue Dec 20 23:22:53 2016
Thread-5 starting at Tue Dec 20 23:22:53 2016
Thread-6 starting at Tue Dec 20 23:22:53 2016
Thread-1 end at Tue Dec 20 23:22:55 2016
remaining Thread-2,Thread-3,Thread-4,Thread-5,Thread-6
Thread-4 end at Tue Dec 20 23:22:55 2016
remaining Thread-2,Thread-3,Thread-5,Thread-6
Thread-2 end at Tue Dec 20 23:22:55 2016
remaining Thread-3,Thread-5,Thread-6
Thread-5 end at Tue Dec 20 23:22:56 2016
remaining Thread-3,Thread-6
Thread-6 end at Tue Dec 20 23:22:57 2016
remaining Thread-3
Thread-3 end at Tue Dec 20 23:22:57 2016
remaining
end!

结果正常了

参考资料:Python核心编程.第四章.Wesley Chun著

原文地址:https://www.cnblogs.com/fcyworld/p/6205003.html