第三周周末自习 (2018-10-27)

2018-10-27  本文已影响0人  雨雨雨90

一、多进程

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人到场!(加锁后的结果!)
上一篇下一篇

猜你喜欢

热点阅读