本文目录
  1. 1、多任务
  2. 1.并行
  3. 2.并发
  4. 2、进程
  5. 1.创建进程
  6. 2. 进程ID
  7. 3.进程之间的数据共享
  8. 4. 守护进程
  9. 3、线程
  10. 1.特点
  11. 2.创建多线程任务
  12. 3.守护多线程
  13. 4. 线程之间的数据共享
  14. 5.互斥锁

Python 进程与线程

掌握多任务、进程、线程、守护任务、数据共享与互斥锁。

1、多任务

同一时间内执行多个任务

1.并行

真正的同一时间进行多个任务——进程

2.并发

一段时间内交替进行多个任务——线程

2、进程

1.创建进程

multiprocessing.Process(target="执行的内容",name="进程名",
                        args=“位置参数”,kwargs=“关键字参数”,daemond=True(守护进程))
import time
import multiprocessing

def lisen():
    for i in range(20):
        print("我在听歌")
        time.sleep(1)


def write():
    for i in range(20):
        print("我在写代码")
        time.sleep(1)


if __name__ == '__main__':

    # 创建进程
    p1 = multiprocessing.Process(target=lisen)
    p2 = multiprocessing.Process(target=write)

    #开始进程
    p1.start()
    p2.start()

2. 进程ID

#获取pid os.pid
#获取父进程id os.ppid
import os
import time

def lisen():
    print("听歌的进程id",os.getpid())
    print("听歌的父进程id",os.getppid())
    for i in range(20):
        print("我在听歌")
        time.sleep(1)


def write():
    print("写代码的进程id",os.getpid())
    print("写代码的父进程id",os.getppid())
    for i in range(20):
        print("我在写代码")
        time.sleep(1)


import multiprocessing

if __name__ == '__main__':
    print("主进程的进程id",os.getpid())
    print("主进程的父进程id",os.getppid())
    # 创建进程
    p1 = multiprocessing.Process(target=lisen)
    p2 = multiprocessing.Process(target=write)

    #开始进程
    p1.start()
    p2.start()

3.进程之间的数据共享

主进程的全局变量子进程无法访问

子进程会自己复制一份主进程的变量

如果要全局访问同一变量,需要使用通道

#进程之前如果想进行数据传输就需要用到管道
import multiprocessing
import time

#新建一个管道
queue=multiprocessing.Queue()
#管道可以有多个
queue2=multiprocessing.Queue()

def fn1(queue):
    for i in range(5):
        #给管道里面放数据
        queue.put(i)
        time.sleep(0.5)
        print(queue)

def fn2(queue):
    for i in range(5):
        #从管道里面取数据
        print(queue.get())
        time.sleep(0.5)

if __name__ == '__main__':
    p1=multiprocessing.Process(target=fn1,args=(queue,))
    p2=multiprocessing.Process(target=fn2,args=(queue,))
    p1.start()
    p2.start()

4. 守护进程

主进程会等待子进程结束后再结束

守护进程:主进程结束时子进程也结束

方法:1.守护进程属性

​ 2.强制结束

import time
import multiprocessing
#现象:主进程结束,子进程会继续执行,直到子进程结束,
 # 主进程等待子进程

 #守护进程:主进程结束,子进程立刻结束
 #方法1:给子进程设置守护进程属性 daemon=True
 #方法2:强制关闭子进程 process.terminate()

def eat():
   for i in range(10):
       print("吃吃吃")
       time.sleep(0.5)

def drink():
   for i in range(10):
       print("喝喝喝")
       time.sleep(0.5)

if __name__ == '__main__':
    p1=multiprocessing.Process(target=eat)
    p2=multiprocessing.Process(target=drink)

    # #设置守护进程属性
    # p1=multiprocessing.Process(target=eat,daemon=True)
    # p2=multiprocessing.Process(target=drink,daemon=True)
    p1.start()
    p2.start()

    for i in range (5):
        print("玩玩玩")
        time.sleep(0.5)
   ## 强制删除子进程
    p1.terminate()
    p2.terminate()

3、线程

1.特点

线程的执行是无序的

主线程会等子线程结束再结束

线程之间共享全局变量

线程访问全局变量会出现错误

2.创建多线程任务

threading.Thread(target="执行的内容",name="进程名",
                        args=“位置参数”,kwargs=“关键字参数”,daemond=True(守护进程)
import time
import threading

def eat():
    for i in range(10):
        print("吃吃吃")
        time.sleep(0.5)

def drink():
    for i in range(10):
        print("喝喝喝")
        time.sleep(0.5)

if __name__ == '__main__':
    p1=threading.Thread(target=eat)
    p2=threading.Thread(target=drink)
    p1.start()
    p2.start()

3.守护多线程

结束的最小单位是程序(进程)

线程要守护就都守护,否则无效

线程不能强制关闭

import time
import threading

def eat():
    for i in range(10):
        print("吃吃吃")
        time.sleep(0.5)

def drink():
    for i in range(10):
        print("喝喝喝")
        time.sleep(0.5)

if __name__ == '__main__':
    #添加守护线程属性
    p1=threading.Thread(target=eat,daemon=True)
    p2=threading.Thread(target=drink, daemon= True)
    p1.start()
    p2.start()

    for i in range(5):
        print("打豆豆")
        time.sleep(0.5)

4. 线程之间的数据共享

线程之间可以全局变量共享,

但由于线程的执行是无序的,所以会导致数据错误

# 抢票
import threading
import time

num=3

def run():
    global num
    num-=1
    print(f"{threading.current_thread().name}抢到一张票,还剩{num}张票")

if __name__ == '__main__':
    t1=threading.Thread(target=run,name="线程1")
    t2=threading.Thread(target=run,name="线程2")
    t3=threading.Thread(target=run,name="线程3")
    t4=threading.Thread(target=run,name="线程4")
    t5=threading.Thread(target=run,name="线程5")

    t1.start()
    t2.start()
    t3.start()
    t4.start()
    t5.start()

5.互斥锁

为解决线程共享全局变量导致数据错误的情况,

可以给函数内增加锁,

锁的作用是让线程一口气执行完这一段代码,以防数据错误

# 抢票
import threading


num=3

def run(lock):
    #添加锁
    # lock.acquire()
    #托管锁
    with lock:
      global num
      if num >0:
         num-=1
         print(f"{threading.current_thread().name}抢到一张票,还剩{num}张票")
    # #解锁
    # lock.release()

if __name__ == '__main__':
    #添加互斥锁
    lock=threading.Lock()

    t1=threading.Thread(target=run,name="线程1",args=(lock,))
    t2=threading.Thread(target=run,name="线程2",args=(lock,))
    t3=threading.Thread(target=run,name="线程3",args=(lock,))
    t4=threading.Thread(target=run,name="线程4",args=(lock,))
    t5=threading.Thread(target=run,name="线程5",args=(lock,))

    t1.start()
    t2.start()
    t3.start()
    t4.start()
    t5.start()