[python]线程与进程的区别及代码演示
进程与线程
多线程socket,tcp服务器实现,在最底下
区别:
关系区别:
线程依赖于进程,一个进程至少会有一个线程
特点区别:
- 进程间的数据是相互隔离的,线程间数据是可以共享的
- 线程同时操作共享数据, 可能引发安全问题,需要用到互斥锁
- 进程的资源开销比线程大
- 多进程程序比 单进程多线程程序要更加的稳定
优缺点:
1.进程:可以多核操作,资源开销较大
2.线程:不能多核,资源开销相对较小
总结:
1.线程依赖进程
2.进程数据隔离,线程数据共享
3.进程资源开销比线程大,更加稳定
4.无论是多线程还是多进程,目的都是:充分利用CPU资源,提高效率
进程格式:
import multiprocessing
if __name__ == '__main__':# 创建进程p1p1 = multiprocessing.Process(target=目标....)# 参数有target进程链接对象 name进程名 args元组形式传参 kwargs字典形式传参#启动进程p1.start()
线程格式:
import threading
if __name__ == '__main__':t1 = threading.Thread(target=....)# 参数和进程一样有target进程链接对象 name进程名 args元组形式传参 kwargs字典形式传参#启动进程t1.start()
图解:
关系示例:
进程:
1.进程之间和main进程的关系
import multiprocessing
import time'''
进程之间数据是相互隔离的
多进程之间针对于main进程的外部资源每个子进程都会拷贝一份进行执行
'''# print('我是mian外')def add_data(my_list):for i in range(5):my_list.append(i)print(f'添加{i}成功!')print(f'add_data函数:{my_list}')def read_data(my_list):time.sleep(1) # 保证add_data先执行print(f'read_data函数:{my_list}')if __name__ == '__main__':my_list = []p1 = multiprocessing.Process(target=add_data, args=(my_list,))p1.start()time.sleep(1)print(my_list)time.sleep(1)p2 = multiprocessing.Process(target=read_data, args=(my_list,))p2.start()print('我是mian内')
2.main默认情况下主进程会等待子进程结束再结束
'''
默认情况下主进程会等待子进程结束再结束
可以设置子进程为守护进程
'''import multiprocessing
import timedef my_method():for i in range(10):print(f'工作中...{i}')time.sleep(0.3)def fun2():passif __name__ == '__main__':# 设置进程为守护链接p1 = multiprocessing.Process(target=my_method, daemon=True)p1.start()time.sleep(1)print('主进程结束')p1.kill()
线程:
1.带参数的多线程示例:
'''
线程是cpu调度资源的基本单位,进程是cpu分配资源的进本单位
进程 = 可执行程序,文件
线程 = 进程的执行路径,执行单元
无论是进程还是线程,都实现多任务的一种方式,目的都是充分利用CPU资源,提高效率
多线程带参数
target : 关联目标函数
name: 线程名或进程名
args: 以元组的形式传参数
kwargs : 以字典的形式传参数
'''
import threading, timedef coding(name, num):for i in range(num):# time.sleep(0.1)print(f'{name}在写代码{i}')def music(name, num):for i in range(num):# time.sleep(0.1)print(f'{name}在听音乐{i}....')if __name__ == '__main__':t1 = threading.Thread(target=coding, args=('小明', 200))t2 = threading.Thread(target=music, kwargs={'name': '小红', 'num': 200})t1.start()t2.start()
2.多线程操控资源的安全性问题,可以通过加锁来避免
无锁版:
'''
多线程的执行具有随机性,就是在强cpu的过程,谁抢到,谁执行
默认情况下主线程会等待子线程执行结束在结束
线程之间会共享当前进程的资源
多线程环境 并发 操作共享资源, 有可能引发安全问题,需要通过 线程同步(加锁) 的思想来解决
CPU的资源分配,调度:
1.均分时间片,即:每个进程(线程)占用CPU的时间都是相等的
2.抢占式调度,谁抢到,谁执行,Python用的这种
多线程并发操作共享全局变量,引发安全问题
'''
import threading
import timenum = 0def add_num():global numfor i in range(1000000):num += 1print(f'1ok:{num}')def add_num2():global numfor i in range(1000000):num += 1print(f'2ok:{num}')if __name__ == '__main__':t1 = threading.Thread(target=add_num)t2 = threading.Thread(target=add_num2)t1.start()t2.start()print(num)
运行结果可以发现同时操作数据后,结果比我们预期的2000000要少
加锁版:
import threading
import timenum = 0
# 定义互斥锁
mutex = threading.Lock()def add_num():#开启锁mutex.acquire()global numfor i in range(1000000):num += 1print(f'1ok:{num}')#关闭锁mutex.release()def add_num2():#开启锁mutex.acquire() # 保证t1和t2操作num是互斥的global numfor i in range(1000000):num += 1print(f'2ok:{num}') #关闭锁mutex.release()if __name__ == '__main__':t1 = threading.Thread(target=add_num)t2 = threading.Thread(target=add_num2)t1.start()t2.start()mutex.acquire()print(num)mutex.release()
这里运行就会输出我们预期的结果.