并发编程:生产消费模型、死锁与Rlock、线程、守护线程、信号量、锁

一、生产者消费者模型1

二、生产者消费者模型2

三、守护线程

四、常用方法

五、启动线程的另一种方式

六、锁

七、锁死

八、死锁

九、单个锁能不能死锁

十、信号旗

 

一、生产者消费者模型1

import time,random
from multiprocessing import Process,Queue
# 制作热狗
def make_hotdog(queue,name):
    for i in range(3):
        time.sleep(random.randint(1,2))
        print("%s 制作了一个热狗 %s" % (name,i))
        # 生产得到的数据
        data = "%s生产的热狗%s" % (name,i)
        # 存到队列中
        queue.put(data)
    # 装入一个特别的数据 告诉消费方 没有了
    #queue.put(None)


# 吃热狗
def eat_hotdog(queue,name):
    while True:
        data = queue.get()
        if not data:break
        time.sleep(random.randint(1, 2))
        print("%s 吃了%s" % (name,data))

if __name__ == '__main__':
    #创建队列
    q = Queue()
    p1 = Process(target=make_hotdog,args=(q,"邵钻钻的热狗店"))
    p2 = Process(target=make_hotdog, args=(q, "egon的热狗店"))
    p3 = Process(target=make_hotdog, args=(q, "老王的热狗店"))


    c1 = Process(target=eat_hotdog, args=(q,"思聪"))
    c2 = Process(target=eat_hotdog, args=(q, "李哲"))

    p1.start()
    p2.start()
    p3.start()

    c1.start()
    c2.start()

    # 让主进程等三家店全都做完后....
    p1.join()
    p2.join()
    p3.join()

    # 添加结束标志   注意这种方法有几个消费者就加几个None 不太合适 不清楚将来有多少消费者
    q.put(None)
    q.put(None)


    # 现在 需要知道什么时候做完热狗了 生产者不知道  消费者也不知道
    # 只有队列知道



    print("主进程over")





    # 生产方不生产了 然而消费方不知道 所以已知等待  get函数阻塞
    # 三家店都放了一个空表示没热狗了  但是消费者只有两个 他们只要看见None 就认为没有了
    # 于是进程也就结束了  造成一些数据没有被处理
    # 等待做有店都做完热狗在放None

 

二、生产者消费者模型2

import time,random
from multiprocessing import Process,JoinableQueue
# 制作热狗
def make_hotdog(queue,name):
    for i in range(3):
        time.sleep(random.randint(1,2))
        print("%s 制作了一个热狗 %s" % (name,i))
        # 生产得到的数据
        data = "%s生产的热狗%s" % (name,i)
        # 存到队列中
        queue.put(data)
    # 装入一个特别的数据 告诉消费方 没有了
    #queue.put(None)

# 吃热狗
def eat_hotdog(queue,name):
    while True:
        data = queue.get()
        time.sleep(random.randint(1, 2))
        print("%s 吃了%s" % (name,data))
        # 该函数就是用来记录一共给消费方多少数据了 就是get次数
        queue.task_done()


if __name__ == '__main__':
    #创建队列
    q = JoinableQueue()
    p1 = Process(target=make_hotdog,args=(q,"邵钻钻的热狗店"))
    p2 = Process(target=make_hotdog, args=(q, "egon的热狗店"))
    p3 = Process(target=make_hotdog, args=(q, "老王的热狗店"))


    c1 = Process(target=eat_hotdog, args=(q,"思聪"))
    c2 = Process(target=eat_hotdog, args=(q, "李哲"))

    p1.start()
    p2.start()
    p3.start()

    # 将消费者作为主进程的守护进程
    c1.daemon = True
    c2.daemon = True


    c1.start()
    c2.start()

    # 让主进程等三家店全都做完后....
    p1.join()
    p2.join()
    p3.join()


    # 如何知道生产方生产完了 并且 消费方也吃完了

    # 方法一:等待做有店都做完热狗在放None
    # # 添加结束标志   注意这种方法有几个消费者就加几个None 不太合适 不清楚将来有多少消费者
    # q.put(None)
    # q.put(None)

    # 主进程等到队列结束时再继续  那队列什么时候算结束? 生产者已经生产完了 并且消费者把数据全取完了
    q.join()  # 已经明确生产放一共有多少数据

    # 现在 需要知道什么时候做完热狗了 生产者不知道  消费者也不知道
    # 只有队列知道

    print("主进程over")
    # 生产方不生产了 然而消费方不知道 所以一直等待  get函数阻塞
    # 三家店都放了一个空表示没热狗了  但是消费者只有两个 他们只要看见None 就认为没有了
    # 于是进程也就结束了  造成一些数据没有被处理

 

三、守护线程

from threading import Thread
import time

def task():
time.sleep(5)
print("子线程...")

t = Thread(target=task)
t.daemon = True # 守护线程 执行顺序与进程中一样
t.start()
print("over")

 

四、线程

from threading import Thread

# a = 100
#
# def task():
#     global a
#     a = 1
#     print("这是给子线程执行的任务!")
#
# # 创建一个子线程
# t = Thread(target=task)
# # 启动这个子线程
# t.start()
# print("主")
# print(a)

# 在多进程中 开启子进程需要消耗大量的资源  所以主进程会先比子进程执行
# 子线程的开启速度比进程快的多
# 在多线程中 子线程可以直接访问主线程的内容
# 多个线程之间时平等的   所以不存在父子关系
# 在今后的开发中 每当出现i/o阻塞  比较耗时的操作

import time,os

def task():
    time.sleep(2)
    print("子线程 run.....")
    print(os.getpid())

t = Thread(target=task)
t.start()
# 主线程等到子线程结束
t.join()
print("over")
print(os.getpid())

 

 

五、常用方法

from threading import Thread,current_thread,active_count,enumerate
import time

def task():
    print("子线程...")
    time.sleep(1)
    # 获取当前线程对象  非常常用
    print(current_thread())

t = Thread(target=task,name="矮根线程!")
# t.daemon = True  # 守护线程  执行顺序与进程中一样
print(t.name)
print(t)
t.start()
# 获取当前活跃线程的数量
print(active_count())
# 返回活跃的线程对象枚举
print(enumerate())
print("over")

 

六、启动线程的另一种方式

from threading import Thread,current_thread

class MyThread(Thread):
    def run(self):
        print("run 函数执行!")
        print(current_thread())

mt = MyThread()
mt.start()

print(current_thread())

 

 

七、锁

from threading import Thread,Lock
# 创建一个互斥锁
mutex = Lock()

def task1():
    # 锁定
    mutex.acquire()
    for i in range(100):
        print("===================")
    # 打开
    mutex.release()
def task2():
    mutex.acquire()
    for i in range(100):
        print("!!!!!!!!!!!!!!!!!!")
    mutex.release()

def task3():
    mutex.acquire()
    for i in range(100):
        print("********************")
    mutex.release()

t1 = Thread(target=task1)
t2 = Thread(target=task2)
t3 = Thread(target=task3)

t1.start()
t2.start()
t3.start()

 

八、锁死

from threading import Thread,Lock
import time,random

mutex1 = Lock()
mutex2 = Lock()
def fun1():
mutex1.acquire()
print("抢到了锁1")
time.sleep(1)
mutex2.acquire()
print("抢到了锁2")

mutex2.release()
print("释放了锁2")

mutex1.release()
print("释放了锁1")


def fun2():

mutex2.acquire()
print("抢到了锁2")

time.sleep(1)

mutex1.acquire()
print("抢到了锁1")



mutex1.release()
print("释放了锁2")

mutex2.release()
print("释放了锁1")

# def fun3():
# fun1()
# fun2(

t1 = Thread(target=fun1)
t1.start()
t2 = Thread(target=fun2)
t2.start()






 

九、死锁

from threading import Thread,Lock,current_thread,RLock
import time
# 叉子
locka = RLock()
# 盘子
lockb = RLock()



def task1():
    print(current_thread())
    locka.acquire()
    print("抢到叉子 需要盘子")
    time.sleep(0.1)
    lockb.acquire()
    print("吃饭")

    lockb.release()
    locka.release()

def task2():
    print(current_thread())
    lockb.acquire()
    print("抢到盘子 需要叉子")
    time.sleep(0.1)
    locka.acquire()

    print("吃饭")
    locka.release()
    lockb.release()


t1 = Thread(target=task1)
t1.start()
t2 = Thread(target=task2)
t2.start()

# 死锁发生的条件  有多个线程 多个锁   如果只有一个锁 无论是LOCK RLOK 卡不死(前提是逻辑上没有错误)
# RLock 就算你的代码逻辑不对 同一个线程多次对一个锁执行acquire 也不会卡死

 

十、单个锁能不能死锁

from threading import  Thread,Lock,RLock,current_thread

l = Lock()  # 互斥锁

# l.acquire()
# print("zxxzxxxzxzx")
# l.acquire()
# print("aaaaaaaaa")


# RLock   递归锁 重入锁  可以多次执行acquire

# lock = RLock()
#
# lock.acquire()
# print("aaaaaaaaaaa")
# lock.acquire()
# print("bbbbbbbbbbb")



import time
lock = RLock()
# 对于同一个线程而言 可以多次acquire  其他线程会被阻塞
def task():
    lock.acquire()
    for i in range(5):
        time.sleep(1)
        print(current_thread())
    lock.release()

Thread(target=task).start()
Thread(target=task).start()


#

 

十一、信号旗

from threading import Thread,Semaphore,current_thread,active_count

import time
# 用于控制 同时执行被锁定代码的线程数量   也就是线程的并发数量
# 也是一种锁
sm = Semaphore(1)

def task():
    sm.acquire()
    for i in range(10):
        print(current_thread())
        time.sleep(0.5)
    sm.release()

def task2():
     for i in range(10):
        print(current_thread())
        time.sleep(0.5)


for i in range(5):
    Thread(target=task).start()
    Thread(target=task2).start()
print(active_count())

 

线程和进程的区别

  进程是一个资源单位

  一个进程可以包含多个线程

  多个线程之间的数据可以共享

  线程开销比进程小

  在多个线程中CPU切换速度会比非常快,但资源消耗没有进程高

 

转载于:https://www.cnblogs.com/wuzhengzheng/p/10273437.html

你可能感兴趣的:(并发编程:生产消费模型、死锁与Rlock、线程、守护线程、信号量、锁)