一、多进程
python中,windows可以用multiprocessing模块引入多进程,使用Process类创建进程,用函数名和函数参数作为类的构建函数参数,进而创建在父进程下创建新的子进程
最简多进程编程如下例:
from multiprocessing import Process
from os import getpid
from random import randint
import time
def eating(name, place):
print('%s开始在%s吃饭' % (name, place))
print('当前进程号:%s' % getpid())
duration = randint(5, 10)
time.sleep(duration)
print('%s在%s吃了%s分钟,吃完了,真香!' % (name, place, duration))
print(time.time())
def main():
p1 = Process(target=eating, args=('小明', '天台'))
p2 = Process(target=eating, args=('小张', '厕所'))
print(time.time())
p1.start()
p2.start()
if __name__ == '__main__':
main()
# 1540612569.8932595
# 小明开始在天台吃饭
# 当前进程号:19324
# 小张开始在厕所吃饭
# 当前进程号:18724
# 小张在厕所吃了7分钟,吃完了,真香!
# 1540612577.1456742
# 小明在天台吃了9分钟,吃完了,真香!
# 1540612579.138788
二、多线程中全局变量的保护
如果一个资源被多个线程竞争使用,那么我们通常称之为“临界资源”,对“临界资源”的访问需要加上保护,否则资源会处于“混乱”的状态。
import threading
import time
class Exhibition:
"""展览类"""
def __init__(self, name):
self._name = name
self._visitor_num = 0
@property
def name(self):
return self._name
@property
def visitor_num(self):
return self._visitor_num
def accept_visitor(self, num):
new_num = self._visitor_num + num
time.sleep(0.01)
self._visitor_num = new_num
class GuestEnterThread(threading.Thread):
"""游客进入通道,一个游客对应一个通道"""
def __init__(self, exhibition):
super().__init__()
self.exhibition = exhibition
def run(self):
self.exhibition.accept_visitor(1) # 每次进入两个人
def main():
exhibition = Exhibition('汽车展')
threads = []
for i in range(0, 100):
t = GuestEnterThread(exhibition)
threads.append(t)
t.start()
for item in threads:
item.join()
print('%s今天有%s人到场!' % (exhibition.name, exhibition.visitor_num))
if __name__ == '__main__':
main()
# 汽车展今天有2人到场!(远远小于100)
多个线程同时执行到new_num = self._visitor_num + num
这个代码,多个线程得到的self._visitor还是初始的0状态(调试代码时,在self._visitor_num = new_num加了线程阻塞延时,让self._visitor_num更新速度变慢,得出了临界资源出现混乱的情况)
因此,需要通过'锁'保护‘临界资源’:
import threading
import time
class Exhibition:
"""展览类"""
def __init__(self, name):
self._name = name
self._visitor_num = 0
self._lock = threading.Lock()
@property
def name(self):
return self._name
@property
def visitor_num(self):
return self._visitor_num
def accept_visitor(self, num):
# 在此处加'锁’保护临界资源'self._visitor_num'
self._lock.acquire()
try:
new_num = self._visitor_num + num
time.sleep(0.01)
self._visitor_num = new_num
# 确保异常或者正常都能解除锁定
finally:
self._lock.release()
class GuestEnterThread(threading.Thread):
"""游客进入通道,一个游客对应一个通道"""
def __init__(self, exhibition):
super().__init__()
self.exhibition = exhibition
def run(self):
self.exhibition.accept_visitor(1) # 每次进入两个人
def main():
exhibition = Exhibition('汽车展')
threads = []
for i in range(0, 100):
t = GuestEnterThread(exhibition)
threads.append(t)
t.start()
for item in threads:
item.join()
print('%s今天有%s人到场!' % (exhibition.name, exhibition.visitor_num))
if __name__ == '__main__':
main()
# 汽车展今天有100人到场!(加锁后的结果!)
网友评论