进程与线程

操作系统/进程

程序

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()
posted on 2019-07-24 16:35  _albert  阅读(107)  评论(0编辑  收藏  举报