并发编程 #2

一、进程锁

前言

锁在IT界都是非常重要的,不单单只有在Python中出现,尤其是数据库中的锁更多。比如:表锁、行锁、悲观锁、乐观锁、进程锁、互斥锁、递归锁、可重入锁、死锁、等···

1. 多进程抢占资源

当多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题。

from multiprocessing import Process  # 导入进程模块
import time  # 导入时间模块


def index(i):  # 创建一个函数来作为子进程执行代码
    print(f'进程{i}进来了')
    time.sleep(1)
    print(f'进程{i}离开了')


if __name__ == '__main__':  # 进程必须在__name__ 中运行
    for i in range(5):   # 循环执行子进程5次
        p = Process(target=index, args=(i+1,))  # 实例化执行对象
        p.start()  # 开始执行进程


# 打印结果:
进程1进来了
进程2进来了
进程5进来了
进程3进来了
进程4进来了
进程2离开了进程1离开了

进程3离开了进程4离开了
进程5离开了

2. 加上进程锁

由并发变成了串行,牺牲了运行效率,但避免了竞争

from multiprocessing import Process, Lock  # 导入进程模块和进程锁模块
import time  # 导入时间模块


def index(i, lock):
    lock.acquire()  # 上锁
    print('进程%s进来' % i)
    time.sleep(1)
    print('进程%s离开' % i)
    lock.release()  # 解锁


if __name__ == '__main__':
    lock = Lock()
    for i in range(5):
        p = Process(target=index, args=(i + 1, lock))
        p.start()


打印结果
进程2进来
进程2离开
进程3进来
进程3离开
进程1进来
进程1离开
进程5进来
进程5离开
进程4进来
进程4离开

二、如何查看进程号

import time, os
from multiprocessing import Process


def index():
    print('index的子进程号:', os.getpid())
    print('查看index子进程的父进程号:', os.getppid())
    time.sleep(5)


if __name__ == "__main__":
    p = Process(target=index)
    p.start()
    print('查看子进程号:', p.pid)
    print('查看主进程号:', os.getpid())
    time.sleep(10)


打印结果:
查看子进程号: 11920
查看主进程号: 27780
index的子进程号: 11920
查看index子进程的父进程号: 27780

三、进程之间数据隔离问题

n=100

def task():
    global n
    n=1
    print("子进程")


from multiprocessing import Process

"""这两个进程之间的数据有没有通信? 么有通信"""
if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    """先让子进程先执行,让子进程去改值"""
    p.join()
    print("主进程中得值:", n)
    
"""问题是:如何让进程与进程之间数据通信? """

四、队列(Queue)

存储数据的地方,所有主进程和子进程都可以存数据或者取数据

from multiprocessing import Queue

q = Queue(3) # 括号内指定存储数据的个数,默认可以存SEM_VALUE_MAX =
#1. 往消息队列种存放数据
q.put(111)
print(q.full())  # 判断队列是否已满  False
q.put(222)
q.put(333)
print(q.full())  # 判断队列是否已满  True
#2.从消息队列取出数据
print(q.get())  # 111
print(q.empty())  # 判断队列是否为空  False
print(q.get())  # 222
print(q.get())  # 333
# print(q.empty())  # 判断队列是否为空  True
# print(q.get())  # 数据拿不到值,就会一直等着,处于阻塞态

print(q.get_nowait())  # 如果队列没有数据,会直接报错
"""full() empty()  在多进程种都不能使用,判断会出现失误,
执行q.full()是True,在极限情况,当队列满的时候,当一个进程执行q.get(),队列的数据会被拿走
执行q.empty()是true,在极限情况,队列是空的时候,你执行q.empty是空的下一秒有一个进程往里面存数据,此时的队列不是空的
,"""
生产者消费者模型
rom multiprocessing import Process, Queue


def product(q, bool):
    for i in range(10):
        q.put('这是我生产的%s个%s' % (i + 1, bool))


def consumer(q):
    while True:
        res = q.get()
        print(res)
        if res is None:
            break


if __name__ == '__main__':
    q = Queue(10)

    # 生产者
    p1 = Process(target=product, args=(q, '包子'))
    p2 = Process(target=product, args=(q, '饺子'))
    p3 = Process(target=product, args=(q, '馒头'))
    p4 = Process(target=product, args=(q, '鸡蛋'))


    # 消费者
    c = Process(target=consumer, args=(q,))
    c.start()

    p1.start()
    p1.join()
    p2.start()
    p2.join()
    p3.start()
    p3.join()
    p4.start()
    p4.join()
    q.put(None)

四、线程

在一个进程中,线程就是必须存在的,至少要有一个线程来执行任务
一个进程中可以有多个线程,在一个进程中可有开启多个线程来执行任务
进程和线程都是有操作系统调度的
进程是操作系统分配资源的基本单位,线程是操作系统执行的最小单位

如何开启线程? 跟开进程是一样的

import time
def task(a, b):
    print("from task")
    time.sleep(2)
    print("aaa")


from  multiprocessing import Process
from threading import Thread
import threading
if __name__ == '__main__':
    # p=Process(target=task)
    # p.start()
    # deamon
    """开线程的资源非常小,以至于代码走到这一行就立马开起来了,所以就会立刻执行"""
    t=Thread(target=task, name='Thread-2', args=('a', ), kwargs={'b':1})
    # t.setDaemon(True)
    """设置为了守护进程:主进程结束,子进程跟着结束"""
    t.daemon = True # 把该线程设置为守护线程, 主线程执行完毕,子线程也结束
    """守护线程有什么用?"""
    t.start()
    # t.join()
    # print(t.name)
    """一个进程中如果只有一个线程,该线程称之为是主线程,其他线程称之为是子线程"""
    t.is_alive()
    print(t.getName()) # t.name
    t.setName('aaaa')
    # t.name = 'aaa'
    print("主线程")
    print(threading.currentThread())
    print(threading.enumerate())
    print(threading.activeCount())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《Go并发编程实战第2版PDF》是一本介绍Go语言并发编程的实践指南。本书囊括了Go语言中哪些方面的内容呢? 首先,本书从基础开始介绍了并发编程的基本概念和Go语言的并发模型。它详细解释了Goroutine、Channel以及如何使用它们来实现并发编程。读者可以通过本书学习到如何创建和管理Goroutine,如何使用Channel进行消息传递等。 其次,本书还介绍了如何使用Go语言的并发控制机制,如互斥锁、读写锁和条件变量。通过学习这些机制,读者可以了解如何在多个Goroutine之间共享数据并保证数据的安全性和一致性。 此外,本书还探讨了Go语言中的并发模式和并发算法。它介绍了工作池、并发Map、并发队列等常用的并发模式,并通过示例代码演示了如何使用它们解决实际问题。同时,本书还介绍了一些高级的并发算法,如无锁数据结构和原子操作等,帮助读者更深入地理解并发编程的内部机制。 最后,本书还通过实际案例的方式,介绍了如何使用Go语言进行网络编程和并发IO操作。它涵盖了TCP和UDP的网络编程,以及使用Go语言实现并发的文件读写和网络通信等操作。 总而言之,《Go并发编程实战第2版PDF》是一本非常实用的指南,适合有一定Go语言基础的开发者学习和实践。通过阅读本书,读者可以系统地学习和掌握Go语言并发编程的技术,提高程序的并发能力和性能。 ### 回答2: 《Go并发编程实战 第2版pdf》是一本介绍Go语言并发编程的实战指南。它由多位专业的Go语言开发者合作编写而成,非常适合想要学习并发编程的人士阅读和实践。 这本书从基础知识开始,详细介绍了Go语言中并发编程的核心概念和技术。它包含了大量实际的例子和案例,通过这些实例,读者可以学习如何使用Go语言的并发机制来解决现实世界中的问题。 在《Go并发编程实战 第2版pdf》中,作者首先介绍了Go语言的并发原理和基本概念,比如goroutine和channel等。接下来,他们讨论了如何使用这些概念来构建高效的并发程序,并解决相关的问题,如数据竞争和死锁等。 此外,本书还涵盖了一些高级的主题,例如并发编程模式、并发数据结构、并发的网络编程和并发调试等。这些内容有助于读者深入理解并发编程的原理和实践,并在实际项目中应用它们。 总的来说,《Go并发编程实战 第2版pdf》是一本很好的学习资源,它结合了理论和实践,帮助读者掌握Go语言中并发编程的技巧和策略。无论是想要成为一名优秀的Go语言开发者,还是希望提升对并发编程的理解和应用能力,都可以从这本书中收获很多。 ### 回答3: 《Go并发编程实战 第2版 PDF》是一本关于Go语言并发编程的实战指南。该书通过实际的示例和案例,向读者介绍了Go语言的并发编程概念、原理和技术,并提供了丰富的实战经验和最佳实践。 该书的第2版在第1版的基础上进行了更新和扩展,包含了更多的案例和实践经验。书中主要介绍了Go语言中的并发模型、并发安全、并发编程的基本原则等内容。同时,还介绍了Go语言中常用的并发编程工具和库,如goroutine、channel、互斥锁、条件变量等。 读者通过学习《Go并发编程实战 第2版 PDF》,可以了解到如何使用Go语言进行高效的并发编程。书中详细介绍了如何创建、管理和同步goroutine,如何使用channel进行数据传递和同步,并提供了各种实用的并发编程技巧和最佳实践。 此外,书中还介绍了如何进行并发安全的编程,包括如何使用互斥锁和条件变量进行数据的保护和同步。同时,还介绍了如何进行并发测试,包括常用的测试工具和测试技巧。 总之,《Go并发编程实战 第2版 PDF》是一本权威的Go语言并发编程指南,对于想要学习和提升Go语言并发编程技术的读者来说是一本非常有价值的参考书。通过阅读该书,读者可以系统地学习和掌握Go语言的并发编程技术,提高自己的并发编程能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值