0501-并发通信

独立的进程内存空间

进程是独立的,互不干扰的独立内存空间

import multiprocessing

a = 1
def func():
   global a
   a=a+1


process = multiprocessing.Process(target=func)
process.start()
process.join()
print(a)
1

1530843855483

主进程a=1 , 子进程a=1 并修改为2

进程间通信的解决方案

1530843867853

共享的服务器进程空间

Manger对象的基本使用

进程间通信

from multiprocessing import Manager,Process

mgr = Manager()         # 创建一个服务器进程 并返回与其通信的管理器
list_proxy = mgr.list()  # 通过管理器在服务器进程中开辟一个列表空间,并返回一个代理
list_proxy.append('w')

def func(list_proxy):
    list_proxy[0] = 'r'


print(list_proxy)

#将代理传给子进程 子进程可以通过这个代理 来操作共享空间 进行通信了
p = Process(target=func,args=(list_proxy,))
p.start()
p.join()

print(list_proxy)
print(type(list_proxy))
['w']
['r']
<class 'multiprocessing.managers.ListProxy'>

一般常用的空间类型是:

  1. mgr.list()
  2. mgr.dict()
  3. mgr.Queue()
Windows下python3的解释器

进程部分放到 if name == ‘main‘:下

from multiprocessing import Manager,Process


def func(list_proxy):
    list_proxy[0] = 2


if __name__ == '__main__':

    mgr = Manager()  # 启动服务器进程
    list_proxy = mgr.list()  # 开辟一个列表空间
    list_proxy.append(1)

    p = Process(target=func,args=(list_proxy,))
    p.start()
    p.join()

    print(list_proxy)
    print(type(list_proxy))

线程间共享的全局变量

线程间全局变量的共享

线程属于同一个进程,因此它们之间共享内存区域,全局变量是公共的。

from threading import Thread

a = 1


def func():
   global a
   a = 2


mythread = Thread()
mythread.start()
print(a)
1

共享内存间存在竞争问题

from threading import Thread

a = 0
n = 1000


def add(n):
   global a
   for i in range(n):
      a = a+1


def sub(n):
   global a
   for i in range(n):
      a = a-1


mythread = Thread(target=add,args=(n,))
mythread1 = Thread(target=sub,args=(n,))

mythread.start()
mythread1.start()

mythread.join()
mythread1.join()

print(a)
0
from threading import Thread

a = 0
n = 10000000


def add(n):
   global a
   for i in range(n):
      a = a+1


def sub(n):
   global a
   for i in range(n):
      a = a-1


mythread = Thread(target=add,args=(n,))
mythread1 = Thread(target=sub,args=(n,))

mythread.start()
mythread1.start()

mythread.join()
mythread1.join()

print(a)
-707714

同步锁的基本概念

使用锁来控制共享资源的访问

lock.acquire() 加锁
lock.release() # 释放锁

from threading import Thread,Lock

a = 0
n = 10000000
lock = Lock()   # 生成一把锁


def add(n):
   global a
   for i in range(n):
      lock.acquire()  # 加锁
      a = a+1
      lock.release()  # 释放锁


def sub(n):
   global a
   for i in range(n):
      lock.acquire()  # 加锁
      a = a-1
      lock.acquire() # 释放锁


mythread = Thread(target=add,args=(n,))
mythread1 = Thread(target=sub,args=(n,))

mythread.start()
mythread1.start()

mythread.join()
mythread1.join()

print(a)
0

with lock: # 加锁 自动释放

from threading import Thread,Lock

a = 0
n = 10000000
lock = Lock()  # 生成一把锁


def add(n):
   global a
   for i in range(n):
      with lock:  # 加锁 自动释放
         a = a+1


def sub(n):
   global a
   for i in range(n):
      with lock:  # 加锁 自动释放
         a = a-1


mythread = Thread(target=add,args=(n,))
mythread1 = Thread(target=sub,args=(n,))

mythread.start()
mythread1.start()

mythread.join()
mythread1.join()

print(a)
0

线程与进程安全的队列

队列的基本概念

一个入口,一个出口 先入先出(FIFO)

不需要加锁 不需要考虑竞争问题 队列里已经解决了 所以是安全队列

线程安全队列操作 queue.Queue

入队: put(item)

出队: get()

测试空: empty() # 近似

测试满: full() # 近似

队列长度: qsize() # 近似

任务结束: task_done()

等待完成: join()

import queue

q = queue.Queue(5) # 生成一个安全队列  只能放5个数据
print(q.qsize())
q.put('w')   # 入队
print(q.qsize())
print(q.get())  # 出队
print(q.empty())
print(q.full())
0
1
w
True
False
进程安全队列操作 mgr.Queue

入队: put(item)

出队: get()

测试空: empty() # 近似

测试满: full() # 近似

测试满: full() # 近似

from multiprocessing import Manager


mgr = Manager()
a = mgr.Queue()

a.put('w')
print(a.get())
w

队列算公共资源嘛?

如果只是一个线程/进程在使用,那么它并不算公共资源。但是一旦多个线程/进程在同时使用,那么它就是一个公共资源。

我们是否需要对其加锁?

如果被当作公共资源使用,那么按理说是必须要加锁的。但是,线程安全或进程安全的队列中已经帮我们实现了锁。因此我们不需要再自己使用锁来同步。

生产者与消费者模型

生产者与消费者模型,本质上是把进程通信的问题分开考虑

生产者,只需要往队列里面丢东西(生产者不需要关心消费者)

消费者,只需要从队列里面拿东西(消费者也不需要关心生产者)

1530843910268

from threading import Thread
from queue import Queue
import random


class Producer(Thread):
    def __init__(self,queue):
        super().__init__()
        self.queue = queue

    def run(self):
        while True:
            item = random.randint(0,99)
            self.queue.put(item)
            print('生产者 生产了:%s' % (item))


class Concumer(Thread):
    def __init__(self,queue):
        super().__init__()
        self.queue = queue

    def run(self):
        while True:
            item = self.queue.get()
            print('消费者 从队列中拿出%s' % (item))


queue = Queue(3)
concumer = Concumer(queue)
producer = Producer(queue)
concumer.start()
producer.start()
生产者 生产了:86
生产者 生产了:5
生产者 生产了:81
生产者 生产了:74
消费者 从队列中拿出86
生产者 生产了:64
消费者 从队列中拿出5
生产者 生产了:82
消费者 从队列中拿出81
生产者 生产了:70
消费者 从队列中拿出74
生产者 生产了:37
消费者 从队列中拿出64
。。。。。。

作业: 实现多进程的生产者与消费者模式

from multiprocessing import Process,Manager
import random


class Producer(Process):
    def __init__(self, queue):
        super().__init__()
        self.queue = queue

    def run(self):
        while True:
            item = random.randint(0, 99)  # 假装生成一个数据
            print('生产者 生产了:%s' % (item))
            self.queue.put(item)


class Concumer(Process):
    def __init__(self, queue):
        super().__init__()
        self.queue = queue

    def run(self):
        while True:
            item = self.queue.get()  # 从对队列中拿数据
            print('消费者 从队列中拿出%s' % (item))


mgr = Manager()  # 开启了用来通信的服务器进程 守护进程
queue = mgr.Queue(3)

producer = Producer(queue)  # 生产者
producer.daemon = True
concumer = Concumer(queue)  # 消费者
concumer.daemon = True  # 在start之前开守护

concumer.start()
producer.start()

# 等待输入  让主进程不退出
input()
# 进程代码执行完退出的时候会杀死守护进程

# concumer.join()  # 里面是while True 一直put
生产者 生产了:94
消费者 从队列中拿出94
生产者 生产了:31
消费者 从队列中拿出31
生产者 生产了:16
消费者 从队列中拿出16
生产者 生产了:7
消费者 从队列中拿出7
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值