您好,欢迎访问一九零五行业门户网

Python多线程中线程间资源共享和常用的锁机制的介绍

本篇文章给大家带来的内容是关于python多线程中线程间资源共享和常用的锁机制的介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
本文将简单介绍多线程编程中的线程间资源共享和常用的锁机制。
在多线程编程中,常常会涉及到线程间的资源共享, 常用资源共享常用方式:
全局变量(global)
queue(from queue import queue)
常用的资源共享锁机制:
lock
rlock
semphore
condition
(一) 线程间资源共享使用全局变量可以实现线程间的资源共享,关键字global
代码演示:
from threading import thread, locklock = lock()total = 0'''如果不使用lock那么,最后得到的数字不一定为0;同时loack不支持连续多次acquire,如果这样做了的后果是死锁!'''def add(): global total global lock for i in range(1000000): lock.acquire() total += 1 lock.release() def sub(): global total global lock for i in range(1000000): lock.acquire() total -= 1 lock.release() thread1 = thread(target=add)thread2 = thread(target=sub)# 将thread1和2设置为守护线程,主线程完成时,子线程也一起结束# thread1.setdaemon(true)# thread1.setdaemon(true)# 启动线程thread1.start()thread2.start()# 阻塞,等待线程1和2完成,如果不使用join,那么主线程完成后,子线程也会自动关闭。thread1.join()thread2.join()total
使用queue共享资源,queue是线程安全的。
from threading import thread, lockfrom queue import queuedef add(q): if q.not_full: q.put(1) def sub(q): if q.not_empty: recv = q.get() print(recv) q.task_done() if __name__ =='__main__': # 设置q最多接收3个任务,queue是线程安全的,所以不需要lock qu = queue(3) thread1 = thread(target=add, args=(qu,)) thread2 = thread(target=sub, args=(qu,)) thread1.start() thread2.start() # q队列堵塞,等待所有任务都被处理完。 qu.join()
(二) 锁(lock/rlock/condition/semphore)lock
lock 不能连续acquire锁,不然会死锁,lock 资源竞争可能会导致死锁。
lock 会降低性能。
from threading import thread, locklock = lock()total = 0'''如果不使用lock那么,最后得到的数字不一定为0;同时lock不支持连续多次acquire,如果这样做了的后果是死锁!'''def add(): global total global lock for i in range(1000000): lock.acquire() total += 1 lock.release() def sub(): global total global lock for i in range(1000000): lock.acquire() total -= 1 lock.release() thread1 = thread(target=add)thread2 = thread(target=sub)# 将thread1和2设置为守护线程,主线程完成时,子线程也一起结束# thread1.setdaemon(true)# thread1.setdaemon(true)# 启动线程thread1.start()thread2.start()# 阻塞,等待线程1和2完成,如果不使用join,那么主线程完成后,子线程也会自动关闭。thread1.join()thread2.join()total
rlock
rlock 可以连续acquire锁,但是需要相应数量的release释放锁
因可以连续获取锁,所以实现了函数内部调用带锁的函数
from threading import thread, lock, rlocklock = rlock()total = 0def add(): global lock global total # rlock实现连续获取锁,但是需要相应数量的release来释放资源 for i in range(1000000): lock.acquire() lock.acquire() total += 1 lock.release() lock.release()def sub(): global lock global total for i in range(1000000): lock.acquire() total -= 1 lock.release()thread1 = thread(target=add)thread2 = thread(target=sub)thread1.start()thread2.start()thread1.join()thread2.join()total
condition 条件变量
condition条件变量服从上下文管理协议:使用with语句获取封闭块持续时间的关联锁。
wait()方法释放锁,然后阻塞,直到另一个线程通过调用notify()或notify_all()唤醒它。一旦被唤醒,wait()重新获得锁并返回。也可以指定超时。
先启动wait接收信号的函数,处于阻塞等待状态,再启动notify的函数发出信号
from threading import thread, condition'''聊天 peaple1 : how are you? peaple2 : i`m fine, thank you! peaple1 : what`s your job? peaple2 : my job is teacher. '''def peaple1(condition): with condition: print('peaple1 : ', 'how are you?') condition.notify() condition.wait() print('peaple1 : ', 'what`s your job?') condition.notify() condition.wait()def peaple2(condition): with condition: condition.wait() print('peaple2 : ', 'i`m fine, thank you!') condition.notify() condition.wait() print('peaple2 : ', 'my job is teacher.') condition.notify()if __name__ == '__main__': cond = condition() thread1 = thread(target=peaple1, args=(cond,)) thread2 = thread(target=peaple2, args=(cond,)) # 此处thread2要比thread1提前启动,因为notify必须要有wait接收;如果先启动thread1,没有wait接收notify信号,那么将会死锁。 thread2.start() thread1.start()# thread1.join()# thread2.join()
semphore
该类实现信号量对象。信号量管理一个原子计数器,表示release()调用的数量减去acquire()调用的数量加上一个初始值。如果需要,acquire()方法会阻塞,直到它可以返回而不使计数器为负。如果没有给出,则值默认为1。
#semaphore 是用于控制进入数量的锁#文件, 读、写, 写一般只是用于一个线程写,读可以允许有多个import threadingimport timeclass htmlspider(threading.thread): def __init__(self, url, sem): super().__init__() self.url = url self.sem = sem def run(self): time.sleep(2) print("download {html} success\n".format(html=self.url)) self.sem.release()class urlproducer(threading.thread): def __init__(self, sem): super().__init__() self.sem = sem def run(self): for i in range(20): self.sem.acquire() html_thread = htmlspider("https://www.baidu.com/{}".format(i), self.sem) html_thread.start()if __name__ == "__main__": # 控制锁的数量, 每次同时会有3个线程获得锁,然后输出 sem = threading.semaphore(3) url_producer = urlproducer(sem) url_producer.start()
(三)简单介绍多进程编程多进程编程中进程间不能实现全局变量共享,也不能使用queue.queue
多进程编程通信需要使用queue,pipe
如果使用进程池进程编程需要使用manger的实例的queue来实现通信
以上就是python多线程中线程间资源共享和常用的锁机制的介绍的详细内容。
其它类似信息

推荐信息