Python之进程与线程
进程与多线程
1. 进程
1.1 什么是进程
- 进程是操作系统分配内存资源的最小单位
- 一个进程之内会默认有一个线程
- 进程是Python程序中执行多任务的一种方式
1.2 多进程的使用
- 进程创建的三步:
- 导入包
import multiprocessing
- 创建进程
- 启动进程
start
- 导入包
import multiprocessing
import time
def dance():
for item in range(1, 5):
print("跳舞...")
time.sleep(0.2)
pass
pass
def sing():
for item in range(1, 5):
print("唱歌...")
time.sleep(0.2)
pass
pass
if __name__ == "__main__":
# group 进程组,默认是None,一般不会使用
# target 所需要执行的任务
# name 进程名,默认是process-1,2,.....
# args 参数(元组类型)
dance_process = multiprocessing.Process(target=dance)
dance_process.start()
sing()
import multiprocessing
import time
def dance():
for item in range(1, 5):
print("跳舞...")
time.sleep(0.2)
pass
pass
def sing():
for item in range(1, 5):
print("唱歌...")
time.sleep(0.2)
pass
pass
if __name__ == "__main__":
dance_process = multiprocessing.Process(target=dance)
sing_process = multiprocessing.Process(target=sing)
dance_process.start()
sing_process.start()
1.3 获取进程的编号
- 获取主进程和子进程编号
os.getpid()
- 在子进程内获取他的父进程编号
os.getppid()
- 通过进程编号停止进程
os.kill(process_id, 9)
import multiprocessing
import time
import os
def dance():
dance_process_id = os.getpid()
print("dance进程编号: ", dance_process_id, multiprocessing.current_process)
dance_process_parent_id = os.getppid()
print("dance父进程编号: ", dance_process_parent_id)
for item in range(1, 5):
print("跳舞...")
time.sleep(0.2)
# 9 表示强行停止该进程
os.kill(dance_process_id, 9)
pass
pass
def sing():
sing_process_id = os.getpid()
print("sing进程编号: ", sing_process_id, multiprocessing.current_process)
for item in range(1, 5):
print("唱歌...")
time.sleep(0.2)
pass
pass
if __name__ == "__main__":
dance_process = multiprocessing.Process(target=dance)
sing_process = multiprocessing.Process(target=sing)
dance_process.start()
sing_process.start()
main_processs_id = os.getpid()
print("主进程编号: ", main_processs_id, multiprocessing.current_process)
1.3 进程执行带有参数的执行方式
- 以元组的方式传递(
args
) - 以字典的方式传递(
kwargs
) - 以元组和字典的方式传递(
args
,kwargs
)
import multiprocessing
def show_info(name, age):
print(name, age)
pass
if __name__ == "__main__":
# 方式一
print_process = multiprocessing.Process(target=show_info, args=("一之濑", 16))
print_process.start()
# 方式二
print_process2 = multiprocessing.Process(target=show_info, kwargs={"name": "周雪", "age": 18})
print_process2.start()
# 方式三
print_process3 = multiprocessing.Process(target=show_info, args=("付佳慧",), kwargs={"age": 19})
print_process3.start()
1.4 进程之间不共享资源
- 进程之间不共享资源的原因
if __name__ == __main__:
的两个作用
import multiprocessing
import time
g_list = list()
def add_list():
for i in range(1, 5):
g_list.append(i)
time.sleep(0.2)
print(i)
pass
pass
def read_list():
print(g_list)
if __name__ == '__main__':
add_process = multiprocessing.Process(target=add_list)
read_process = multiprocessing.Process(target=read_list)
add_process.start()
# join 是当前进程下(主进程),只有当子进程执行完成之后,才得以往下执行
add_process.join()
read_process.start()
print(g_list)
if __name__ == __main__:
的两个作用
- 避免外部导包执行该区域的代码
- 避免windows下,进程产生递归
1.5 主进程会等待子进程执行完才销毁
- 如果子进程是一个死循环会怎么办?
- 主进程销毁之前,销毁子进程
- 让子进程守护主进程,主进程销毁子进程销毁,子进程会依赖于子进程。
import multiprocessing
import time
g_list = list()
def rask():
for i in range(1, 10):
g_list.append(i)
time.sleep(0.2)
print(i)
pass
pass
if __name__ == '__main__':
rask_process = multiprocessing.Process(target=rask)
# 方式一:
# rask_process.daemon = True
rask_process.start()
time.sleep(1)
# 方式二;
rask_process.terminate()
print("over")
2. 线程
2.1 什么是线程
- 线程是操作系统调度运算的最小单位,是进程的实际运作单位。
- 线程自己不拥有系统资源
- 同一个进程下面的线程能够共享进程所拥有的的资源
- 一个线程能够创建或撤销另外一个进程。
- 同一个进程的多个线程能够并发执行
- 线程是执行多任务的一种方式
2.2 线程的使用
- 导入
threading
模块 - 创建子线程
- 启动子线程
import threading
import time
def sing():
for i in range(3):
print("sing...")
time.sleep(0.2)
pass
def dance():
for i in range(3):
print("dance...")
time.sleep(0.2)
pass
if __name__ == '__main__':
sing_thread = threading.Thread(target=sing)
sing_thread.start()
dance_thread = threading.Thread(target=dance)
dance_thread.start()
2.3 使用线程执行带有参数的执行方式
- args
- kwargs
2.4 线程的注意事项
线程之间的执行顺序是无序的
import threading
import time
def rask():
time.sleep(1)
print(threading.current_thread())
pass
if __name__ == '__main__':
for item in range(5):
rask_threading = threading.Thread(target=rask)
rask_threading.start()
pass
执行结果
<Thread(Thread-2, started 18756)>
<Thread(Thread-1, started 20816)>
<Thread(Thread-4, started 18496)>
<Thread(Thread-3, started 7556)>
<Thread(Thread-5, started 20920)>
主线程会等待子线程执行完结果
- 如果子线程是一个死循环的话?
- 让子线程守护主线程
demaon
(就可以结束死循环)
import threading
import time
def rask():
while True:
print("正在执行中.....")
time.sleep(0.2)
pass
pass
if __name__ == '__main__':
# 方法一:
# rask_threading = threading.Thread(target=rask, daemon=True)
rask_threading = threading.Thread(target=rask)
# 方法二
rask_threading.setDaemon(True)
rask_threading.start()
time.sleep(1)
print("over")
线程之间是可以共享数据的
import threading
import time
g_list = list()
def add_list():
for item in range(5):
g_list.append(item)
print(item)
time.sleep(0.2)
pass
pass
def read_list():
print(g_list)
pass
if __name__ == '__main__':
add_thread = threading.Thread(target=add_list)
add_thread.start()
# 当前进程等待add_thread进程执行完之后,才能够往下执行
add_thread.join()
read_thread = threading.Thread(target=read_list)
read_thread.start()
线程之间共享全局变量出现错误的情况
- 两个线程同时访问全局变量
import threading
import time
num = 0
def first():
for item in range(100000):
global num
num = num + 1
pass
print(num)
pass
def second():
for item in range(100000):
global num
num = num + 1
pass
print(num)
pass
if __name__ == '__main__':
first_thread = threading.Thread(target=first)
second_thread = threading.Thread(target=second)
first_thread.start()
# 解决方法
first_thread.join()
second_thread.start()
2.5 互斥锁
lock = threading.Lock()
- 上锁
lock.acquire()
- 释放锁
lock.release
import threading
import time
num = 0
lock = threading.Lock()
def first():
lock.acquire()
for item in range(100000):
global num
num = num + 1
pass
lock.release()
print("rask1:", num)
pass
def second():
lock.acquire()
for item in range(100000):
global num
num = num + 1
pass
lock.release()
print("rask2:", num)
pass
if __name__ == '__main__':
first_thread = threading.Thread(target=first)
second_thread = threading.Thread(target=second)
first_thread.start()
second_thread.start()
第一次写博客,后续会慢慢更新