• 进程与线程


    操作系统/进程

    程序

    1. 程序是什么?

    ​ 一堆文件

    2. 进程是什么?

    ​ 进程就是一个正在执行的文件/程序

    3. 进程被谁执行?

    ​ CPU最终运行你的程序

    ​ 操作系统调度作用,将你的磁盘上的程序加载到内存 , 然后交由CPU去处理 , 一个CPU正在运行的一个程序 , 就叫开启了进程

    操作系统

    1. 操作系统的定义

    ​ 操作系统是存在于硬件和软件之间, 管理 , 协调 , 控制软件和硬件

    2. 操作系统的作用

    1. 把复杂的硬件操作 , 封装成简单清晰的接口
    
    1. 合理调度分配多个进程与CPU的关系

    进程介绍

    1. 串行: 所有的进程 , CPU一个一个的解决
    2. 并发: 单个CPU , 同时执行多个进程(来回切换的运行)
    3. 并行: 多个CPU , 真正的同时运行多个进程
    4. 阻塞: 例如 I/O

    进程的创建

    开启进程 : 内存中开空间 , 加载资源与数据应 , 调用CPU执行 , 可能还会使用这个空间的资源

    由主进程创建一个或多个子进程 , 第一个主进程是操作系统

    py文件中 开启新的子进程 , 只是一个新的入口 , 将全局的所有数据复制一份给子进程

    进程的id

    1. 终端: tasklist | findstr appname
    2. pycharm中 os.getpid() os.getppid()

    join 阻塞

    join阻塞的是主进程 自适应sleep

    守护进程

    daemon 守护进程 主程序死亡子程序跟着死亡

    ## 守护进程
    from multiprocessing import Process
    x = 1000
    
    def task():
        global x
        print(x)
        x = 2
        print(id(x))
        test()   ##@2
    def test():
        print('我被执行了')
    
    if __name__ == '__main__':
        p = Process(target=task)  ##@2
        p.daemon() = True   #先声明
        p.start()           # 再开启
        print(id(x))
    
    from multiprocessing import Process
    import time
    ## 并发 join
    def task(name,s):
        time.sleep(s)
        print(name)
    def test():
        print(11111)
    if __name__ == '__main__':
        t1 = time.time()
        ## 并发
        obj_l = []
        for i in range(1,4):
            p = Process(target=task,args=('x'*i,i))
            p.start()
            obj_l.append(p)
        for func in obj_l:
            func.join()
        print(time.time()-t1)
        print('主进程')
    
    ## 子进程开启时 , 会复制主进程的内容  看@2
    from multiprocessing import Process
    x = 1000
    
    def task():
        global x
        print(x)
        x = 2
        print(id(x))
        test()   ##@2
    def test():
        print('我被执行了')
    
    if __name__ == '__main__':
        p = Process(target=task)  ##@2
        p.start()
        p.terminate()  ## 终止进程
        p.is_alive()  ## 查看进程是否活着
        print(id(x))
        
    

    僵尸进程

    僵尸进程是当子进程比父进程先结束 , 而父进程没有回收子进程 , 释放子进程占用的资源 , 此时子进程将成为一个僵尸进程

    孤儿进程

    如果父进程先退出 , 子进程被init接管 , 这时子进程为孤儿进程

    进程通信

    1. 进程在内存级别不允许通信
    2. 可以同时操作一个文件 , 多进程抢占同一资源时 , 保证结果正确 , 公平性竞争 , 必须保证串行 , 并且上锁
    3. 进程通信要用队列 , FIFO

    互斥锁

    from multiprocessing import Process
    from multiprocessing import Lock
    import time
    ## 互斥锁  一锁一解  遇见阻塞 , cpu还是会切换进程, 但是遇到锁了 , 发现锁被占用
    def task(lock):
        lock.acquire()
        time.sleep(2)
        print(11)
        lock.release()
    
    def task2(lock):
        lock.acquire()
        time.sleep(1)
        print(222)
        lock.release()
    
    if __name__ == '__main__':
        lock = Lock()
        p1= Process(target=task,args=(lock,))
        p2 = Process(target=task2,args=(lock,))
        p1.start()
        p2.start()
    

    队列 Queue

    q = Queue(maxsize = 3)
    q.put(1)
    q.put('str')
    q.put(obj)  
    q.put(xxx,block = True)  # block 默认为True 队列长度是3 再放入一个就会阻塞 
    q.get()
    q.get()
    q.get(timeout = 3)  # 取数据 , 也有block 用法相同 , timeout表示最长阻塞时间
    

    生产者消费者模型

    ​ 合理的调控 , 多个进程生产数据与提取数据 , 中间数据使用队列Queue

    ​ 对生产者消费者解耦 , 平衡了生产力和消费力 , 多用于解决并发的问题

    线程

    进程主要任务 : 开启空间 , 加载数据 , 静态的

    线程: 执行代码 , 动态的

    线程和进程的对比

    1. 开启进程 : 开销非常大 ; 开启线程开销非常小
    2. 开启多进程速度慢 , 开启多线程速度快
    3. 进程之间理论数据不能共享 , 同一进程下的线程是可以数据共享的
    # threading 方法
    from threading import Thread
    import threading 
    def task():
        print(11)
    def task2():
        print(22)
    if __name__ == '__main__':
        t1 = Thread(target=task)
        t2 = Thread(target=task2)
        t1.start()
        t2.start()
        print (threading.current_Thread) # 当前线程
        print (active_count()) # 当前存活线程 
        print(threading.enumerate()) # 枚举线程
        
    

    守护线程

    与守护进程不同 , 守护线程要等到所有线程(非守护线程)结束后才结束

    递归锁 一把锁 RLock

    相同线程可以重复上锁 , 解锁也要解相应的次数

    ## 解决死锁的问题
    from threading import Thread
    from threading import RLock
    import time
    rlock = RLock()
    
    class MyThread(Thread):
        def run(self):
            self.f1()
            self.f2()
    
        def f1(self):
            rlock.acquire()
            print(f'{self.name}获取的了rlock')
            rlock.acquire()
            print(f'{self.name}获取的了rlock')
            rlock.release()
            print(f'{self.name}释放了rlock')
            rlock.release()
            print(f'{self.name}释放了rlock')
    
    
        def f2(self):
            rlock.acquire()
            print(f'{self.name}获取的了rlock')
            time.sleep(1)
            rlock.acquire()
            print(f'{self.name}获取的了rlock')
            rlock.release()
            print(f'{self.name}释放了rlock')
            rlock.release()
            print(f'{self.name}释放了rlock')
    
    
    if __name__ == '__main__':
        for i in range(3):
            t = MyThread()
            t.start()
    

    信号量

    一个锁 , 多个坑 , 可允许多个线程同时进入

    from threading import Semaphore
    from threading import Thread
    import time
    import random
    slock = Semaphore(5)
    
    def task(i):
        slock.acquire()
        print(f'{i},进入')
        time.sleep(random.randint(1,3))
    
        slock.release()
    
    
    if __name__ == '__main__':
        for i in range(20):
            t = Thread(target=task,args=(i,))
            t.start()
    
  • 相关阅读:
    BZOJ1999或洛谷1099&BZOJ2282或洛谷2491 树网的核&[SDOI2011]消防
    BZOJ1912或洛谷3629 [APIO2010]巡逻
    CH6202 黑暗城堡
    POJ2728 Desert King
    JoyOI1391 走廊泼水节
    洛谷1073 最优贸易
    POJ3662或洛谷1948 Telephone Lines
    BZOJ1106 [POI2007]立方体大作战tet
    ubuntu 16.04 安装genymotion
    ubuntu下搭建android开发环境核心篇安装AndroidStudio、sdk、jdk
  • 原文地址:https://www.cnblogs.com/albert0823/p/11239024.html
Copyright © 2020-2023  润新知