• python_并行与并发、多线程


    问题一: 计算机是如何执行程序指令的?

    问题二: 计算机如何实现并发的?

    轮询调度实现并发执行 程序1-8轮询完成,才再CPU上运行

    问题三: 真正的并行需要依赖什么?

    并行需要的核心条件

    多进程实现并行

    问题一: 什么是进程?

    计算机程序是存储在磁盘上的文件。

      只有把它们加载到内存中,并被操作系统调用 它们才会拥有其自己的生命周期。

    进程表示一个正在执行的程序。

      每个进程都有独立地址空间以及其他的辅助数据

    进程(Process)

      是计算机中已运行程序的实例

    问题二: 如何在Python中使用进程?

    import multiprocessing   # 导入进程模块
    import datetime
    import time
    
    def func(data):
    
        while True:
            print(datetime.datetime.now())
    
            sum = data + 100
            print(sum)
            time.sleep(2)
    
            print(datetime.datetime.now())
    
    if __name__ == '__main__':
    
        p = multiprocessing.Process(target=func, args=(123,))    # 创建一个进程,args传参 必须是元组
        p.start()    # 运行线程p
    
        while True:
            time.sleep(2)
            print("我是主进程")

    进程使用步骤

    问题三: 多进程实现并行的必要条件是什么?

    总进程数量不多于 CPU核心数量!

    如果不满足,那么运行的程序都是 轮询调度产生的假象。

    多线程实现并发

     问题一:什么是线程?

    线程被称作轻量级进程。
      线程是进程中的一个实体,操作系统不会为进程分配内存空间,它只有一点在运行中必不可少的资源
    线程被包含在进程中,是进程中的实际运作单位
      同一个进程内的多个线程会共享相同的上下文,
      也就是共享资源(内存和数据)。
    线程(thread)
      是操作系统能够进行运算调度的最小单位

    问题二: 如何在Python中使用线程?

    import multiprocessing  # 引用进程模块
    import threading    # 引用线程模块
    import time
    
    def func(data):
        while True:
            time.sleep(1)
            data += 1
            print(data)
    
    # mult = multiprocessing.Process(target=func, args=(1314,))
    # mult.start()  # 运行进程
    
    thre = threading.Thread(target=func, args=(500,))   # 创建一个线程
    thre.start()  # 运行线程
    
    print("这是主进程")

    进程使用步骤

    问题三: 为什么多线程不是并行?

    稳定性
      进程具有独立的地址空间,一个进程崩溃后,不会对其它进程产生影响。
      线程共享地址空间,一个线程非法操作共享数据崩溃后,整个进程就崩溃了。
    创建开销
      创建进程操作系统是要分配内存空间和一些其他资源的。开销很大
      创建线程操作系统不需要再单独分配资源,开销较小
    切换开销
      不同进程直接是独立的, 切换需要耗费较大资源
      线程共享进程地址空间, 切换开销小

    GIL锁(线程锁)

    Python在设计的时候,还没有多核处理器的概念。
    因此,为了设计方便与线程安全,直接设计了一个锁。
    这个锁要求,任何进程中,一次只能有一个线程在执行。


    因此,并不能为多个线程分配多个CPU。
    所以Python中的线程只能实现并发,
    而不能实现真正的并行。


    但是Python3中的GIL锁有一个很棒的设计,
    在遇到阻塞(不是耗时)的时候,会自动切换线程。

    很多库是基于GIL锁写的,取消代价太大
    进程可以实现并行和并发
    线程只能实现并发

    遇到阻塞就自动切换。
    我们可以利用这种机制来
    充分利用CPU

    那么最后:

    使用多进程与多线程来实现并发服务器

     

    使用多进程与多线程实现并发服务器的关键点
    关键点一: 多进程是并行执行,
                     相当于分别独立得处理各个请求。
    关键点二: 多线程,虽然不能并行运行,
                     但是可以通过避开阻塞切换线程
                     来实现并发的效果,并且不浪费cpu

    服务端实现代码:

    import threading  # 创建一个线程
    import socket
    
    server = socket.socket()
    server.bind(('0.0.0.0', 8888))
    server.listen() # 监听
    
    def workon(conn):
        while True:
            data = conn.recv(1024)
    
            if data == b'':
                conn.close()
                break
            else:
                print("接收到的消息: {}".format(data.decode()))
                conn.send(data)
    
    # 主线程
    while True:
        conn, addr = server.accept()
        print("{}正在连接".format(addr))
    
        # 线程去处理消息
        p = threading.Thread(target=workon, args=(conn,))
        p.start()

    客户端代码:

    import socket
    
    click = socket.socket()
    click.connect(('127.0.0.1', 8888))
    
    while True:
         data = input("请输入你要发送的数据:")
         click.send(data.encode())
         print("接收到的消息: {}".format(click.recv(1024).decode()))

    总结完成!

    作者:含笑半步颠√

    博客链接:https://www.cnblogs.com/lixy-88428977

    声明:本文为博主学习感悟总结,水平有限,如果不当,欢迎指正。如果您认为还不错,欢迎转载。转载与引用请注明作者及出处。

  • 相关阅读:
    约瑟夫问题
    [bzoj] 2049 洞穴勘探 || LCT
    [bzoj] 1597 土地购买 || 斜率优化dp
    [usaco] 2008 Dec Largetst Fence 最大的围栏 2 || dp
    [LNOI] 相逢是问候 || 扩展欧拉函数+线段树
    [bzoj] 1588 营业额统计 || Splay板子题
    [hdu] 5115 Dire Wolf || 区间dp
    [poj] 1651 Multiplication Puzzle || 区间dp
    [bzoj] 1090 字符串折叠 || 区间dp
    [bzoj] 1068 压缩 || 区间dp
  • 原文地址:https://www.cnblogs.com/lixy-88428977/p/9644700.html
Copyright © 2020-2023  润新知