Python多线程同步LockRLockSemaphore
Posted cnwenf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python多线程同步LockRLockSemaphore相关的知识,希望对你有一定的参考价值。
不同步的情况
# encoding: UTF-8
import threading
import time
num = 0
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)
num = num + 1
msg = self.name + ‘ set num to ‘ + str(num)
print msg + "
"
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__ == ‘__main__‘:
test()
## 输出
Thread-2 set num to 1
Thread-1 set num to 2
Thread-5 set num to 4
Thread-3 set num to 5
Thread-4 set num to 5
互斥量(mutex)
Lock
import threading
# 创建锁
mutex = threading.Lock()
# 申请锁
mutex.acquire(True)
# 释放锁
mutex.release()
通过Lock实现多线程同步
# encoding: UTF-8
import threading
import time
num = 0
mutex = threading.Lock() # 创建锁
class MyThread(threading.Thread):
def run(self):
global num
time.sleep(1)
if mutex.acquire(True): # 申请锁,如果没抢占到锁,会一直阻塞(block)
num = num + 1
msg = self.name + ‘ set num to ‘ + str(num)
print msg + "
"
mutex.release() # 释放锁
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__ == ‘__main__‘:
test()
## 输出
Thread-1 set num to 1
Thread-2 set num to 2
Thread-4 set num to 3
Thread-3 set num to 4
Thread-5 set num to 5
使用mutex.acquire
和mutex.release
显得比较繁琐,也不安全(比如编程人员忘记释放锁),可以使用with
来替代。
# encoding: UTF-8
import threading
import time
class MyThread(threading.Thread):
def __init__(self, mutex):
super(MyThread, self).__init__()
self.mutex = mutex
def run(self):
global num
time.sleep(1)
with self.mutex: # with语句,安全申请和释放锁。
num = num + 1
msg = self.name + ‘ set num to ‘ + str(num)
print msg + "
"
num = 0
mutex = threading.Lock()
def test():
for i in range(5):
t = MyThread(mutex)
t.start()
if __name__ == ‘__main__‘:
test()
Lock是不允许递归的,一个线程多次申请,将出现死锁。
import threading
lock = threading.Lock() #Lock对象
lock.acquire()
lock.acquire() #产生了死琐。
lock.release()
lock.release()
RLock(递归锁)
LockRLock这两种琐的主要区别是:
RLock允许在同一线程中被多次acquire。
而Lock却不允许这种情况。
注意:如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。
import threading
rLock = threading.RLock() #RLock对象
rLock.acquire()
rLock.acquire() #在同一线程内,程序不会堵塞。
rLock.release()
rLock.release()
信号量(Semaphore)
信号量管理一个内部计数器,该计数器在每次acquire()调用时递减,在每次release()调用时递增。计数器永远不会低于零;当acquire()发现它为0时,它就阻塞,直到其他线程调用release()。
信号量Semaphore
和互斥量mutex
的最大差别是,信号量允许多个线程同时访问一个对象,而互斥量限制只能一个线程访问对象。
假如有一个连接池connection_pool
维护着三个连接,如果有5个线程并发访问,则容易出现连接池没有可用连接的异常情况。例如:
# encoding: UTF-8
import threading
import time
connection_pool = [‘connection1‘, ‘connection2‘, ‘connection3‘] # 连接池
class MyThread(threading.Thread):
def __init__(self):
super(MyThread, self).__init__()
def run(self):
global connection_pool
time.sleep(1)
connection = connection_pool.pop() # 取出连接
print "get connection %s" % connection + "
"
connection_pool.append(connection) # 放回连接
def test():
for i in range(5):
t = MyThread()
t.start()
if __name__ == ‘__main__‘:
test()
# 输出:
Exception in thread Thread-4:
Traceback (most recent call last):
File "C:Python27lib hreading.py", line 801, in __bootstrap_inner
self.run()
File "./with_Semaphore.py", line 17, in run
connection = connection_pool.pop()
IndexError: pop from empty list
这时,就可以使用Semaphore控制同时访问connection_pool的线程数。
# encoding: UTF-8
import threading
import time
connection_pool = [‘connection1‘, ‘connection2‘, ‘connection3‘]
semaphore = threading.Semaphore(3)
class MyThread(threading.Thread):
def __init__(self, semaphore):
super(MyThread, self).__init__()
self.semaphore = semaphore
def run(self):
global connection_pool
time.sleep(1)
with self.semaphore:
connection = connection_pool.pop()
print "get connection %s" % connection + "
"
connection_pool.append(connection)
def test():
for i in range(5):
t = MyThread(semaphore)
t.start()
if __name__ == ‘__main__‘:
test()
# 输出:
get connection connection3
get connection connection2
get connection connection2
get connection connection2
get connection connection3
以上是关于Python多线程同步LockRLockSemaphore的主要内容,如果未能解决你的问题,请参考以下文章