首页 > 系统相关 >多线程和多进程 - 初窥

多线程和多进程 - 初窥

时间:2024-05-20 09:09:46浏览次数:36  
标签:task1 foo sum py start time 进程 多线程

一、说明

在平常工作中,我们使用top命令查看一台linux服务器的cpu使用情况时,会发现某个进程的cpu使用率会超过100%,这是为什么?

二、举例

实验环境为 CentOS7.6 + Python2.7

1. 多线程、多进程在操作系统中的表现形式

我们首先看两个例子,test1.py和test2.py,都是执行死循环,test1.py两个线程,test2.py两个进程。
【test1.py】 -- 多线程

import threading

def foo():
    while 1:
        pass
 
task1 = threading.Thread(target=foo)
task2 = threading.Thread(target=foo)

task1.start()
task2.start()

执行:python test1.py,然后开启另一个窗口,执行top查看cpu使用情况(如果是多核处理器,按“1”可以看每一个cpu核的使用情况)。
1.png

【test2.py】 -- 多进程

import multiprocessing

def foo():
    while 1:
        pass
 
task1 = multiprocessing.Process(target=foo)
task2 = multiprocessing.Process(target=foo)

task1.start()
task2.start()  

杀掉test1的进程,执行:python test2.py,然后开启另一个窗口,执行top查看cpu使用情况。
2.png

通过上面两个例子可以看到,test1只有一个进程,单个进程的cpu使用率超过100%,且该进程在两个cpu核上执行。test2有两个进程,每个进程的cpu使用率为100%,也在两个cpu核上执行。

2. 单线程、多线程、多进程的运行速度

接下来我们再来看三个例子,test3.py、test4.py和test5.py,都是将值做一亿次减法。test3.py采用单线程,test4.py采用多线程,test5.py采用多进程。
【test3.py】 -- 单线程

import time

N = 100000000

def foo(n):
    while n > 0:
        n -= 1
 
start = time.time()
foo(N)
end = time.time()
print('Time taken in seconds: {}'.format(round(end-start, 2)))
[root@34host ~]# python test3.py 
Time taken in seconds: 2.91

【test4.py】 -- 多线程

import time
import threading

N = 100000000

def foo(n):
    while n > 0:
        n -= 1
 
task1 = threading.Thread(target=foo, args=(N/2,))
task2 = threading.Thread(target=foo, args=(N/2,))

start = time.time()
task1.start()
task2.start()
task1.join()
task2.join()
end = time.time()
print('Time taken in seconds: {}'.format(round(end-start, 2)))
[root@34host ~]# python test4.py 
Time taken in seconds: 6.0

【test5.py】 -- 多进程

import time
import multiprocessing

N = 100000000

def foo(n):
    while n > 0:
        n -= 1
 
task1 = multiprocessing.Process(target=foo, args=(N/2,))
task2 = multiprocessing.Process(target=foo, args=(N/2,))

start = time.time()
task1.start()
task2.start()
task1.join()
task2.join()
end = time.time()
print('Time taken in seconds: {}'.format(round(end-start, 2)))
[root@34host ~]# python test5.py 
Time taken in seconds: 1.48

可以看到多线程比单线程的效率低一倍,多进程比单线程的效率高一倍。我使用多线程的目的无非是想让程序快一点,反而慢了。

3. 单线程、多线程、多进程的执行结果

接下来我们再来看三个例子,test6.py、test7.py和test8.py,都是将值做一千万次加法,最后打印这个值。test6.py采用单线程,test7.py采用多线程,test8.py采用多进程。
【test6.py】 -- 单线程

import time

N = 10000000
sum = 0

def foo(n):
    global sum
    for i in range(0, n):
        sum += 1

start = time.time()        
foo(N)
end = time.time()

print('The value of sum: {}'.format(sum))
print('Time taken in seconds: {}'.format(round(end-start, 2)))
[root@34host ~]# python test6.py 
The value of sum: 10000000
Time taken in seconds: 1.26

【test7.py】 -- 多线程

import time
import threading

N = 10000000
sum = 0

def foo(n):
    global sum
    for i in range(0, n):
        sum += 1
 
task1 = threading.Thread(target=foo, args=(N/2,))
task2 = threading.Thread(target=foo, args=(N/2,))

start = time.time()
task1.start()
task2.start()
task1.join()
task2.join()
end = time.time()

print('The value of sum: {}'.format(sum))
print('Time taken in seconds: {}'.format(round(end-start, 2)))
[root@34host ~]# python test7.py 
The value of sum: 7333348
Time taken in seconds: 1.76

【test8.py】 -- 多进程

import time
import multiprocessing

N = 10000000
sum = 0

def foo(n):
    global sum
    for i in range(0, n):
        sum += 1
 
task1 = multiprocessing.Process(target=foo, args=(N/2,))
task2 = multiprocessing.Process(target=foo, args=(N/2,))

start = time.time()
task1.start()
task2.start()
task1.join()
task2.join()
end = time.time()

print('The value of sum: {}'.format(sum))
print('Time taken in seconds: {}'.format(round(end-start, 2)))
[root@34host ~]# python test8.py 
The value of sum: 0
Time taken in seconds: 0.57

可以看到上面三种不同的写法,得出来的结果都不一样。

我将test7.py和test8.py都改造一下,分别为test9.py和test10.py
【test9.py】 -- 多线程

import time
import threading

N = 10000000
sum = 0
lock = threading.Lock()

def foo(n):
    global sum
    global lock
    for i in range(0, n):
        with lock:        
            sum += 1
 
task1 = threading.Thread(target=foo, args=(N/2,))
task2 = threading.Thread(target=foo, args=(N/2,))

start = time.time()
task1.start()
task2.start()
task1.join()
task2.join()
end = time.time()

print('The value of sum: {}'.format(sum))
print('Time taken in seconds: {}'.format(round(end-start, 2)))
[root@34host ~]# python test9.py 
The value of sum: 10000000
Time taken in seconds: 21.49

【test10.py】 -- 多进程

import time
import multiprocessing

N = 10000000
sum = multiprocessing.Value('i', 0)
lock = multiprocessing.Lock()

def foo(n):
    global sum
    global lock
    for i in range(0, n):
        with lock: 
            sum.value += 1
 
task1 = multiprocessing.Process(target=foo, args=(N/2,))
task2 = multiprocessing.Process(target=foo, args=(N/2,))

start = time.time()
task1.start()
task2.start()
task1.join()
task2.join()
end = time.time()

print('The value of sum: {}'.format(sum.value))
print('Time taken in seconds: {}'.format(round(end-start, 2)))
[root@34host ~]# python test10.py 
The value of sum: 10000000
Time taken in seconds: 41.3

可以看到结果都是正确的了,但是执行的时间却比之前长了很多,而且多进程还要慢于多线程。

三、问题

上面的例子,就在我大脑中产生了很多的疑惑。我后面将依次解开这些谜底。

  1. 多线程跟多进程有什么区别,什么时候用多线程,什么时候用多进程?
  2. 单线程、多线程、多进程的效率问题?
  3. 多线程、多进程在编程的时候有哪些注意事项?

标签:task1,foo,sum,py,start,time,进程,多线程
From: https://www.cnblogs.com/ddzj01/p/18201171

相关文章

  • ptrace attach 修改进程内存
    #include<stdio.h>#include<stdlib.h>#include<sys/ptrace.h>#include<stdint.h>#include<errno.h>#include<sys/wait.h>intmain(intargc,char*argv[]){ void*addr1; void*addr2; pid_tattack_pid=-1; if(......
  • PHP的多样化执行方式(parallel PHP多线程实现,原生协程实现,多进程实现,ZTS、NTS、TS又是
    进程、线程、协程进程:应用程序的启动实例,运行起的代码叫进程,有独立的内存空间,类比工厂的P个(P=1单进程,P>1多进程)车间。线程:线程是CPU调度的最小单位,是进程内的执行单元,多个线程共享所属进程的资源。类比车间内的T个员工(T=1单线程,T>1多线程)车间。协程:类似线程,协程是用户态(CPU受......
  • KPCR进程概念
    1.KPCR进程概念KPCR介绍KPCR是CPU的控制结构FS段寄存器在R0(FS=0x30)的时候指向KPCR结构FS段寄存器在R3(FS=0x3b)的时候指向当前线程的TEB(线程)线程结构是运行在CPU上面,所以线程结构是放在CPU上的kd>dt_KPCRntdll!_KPCR+0x000NtTib:_NT_TIB+0x0......
  • 进程
    2.进程KPROCESS这里我们使用驱动管理程序kd>dt_kprocess86de0d20ntdll!_KPROCESS+0x000Header:_DISPATCHER_HEADER+0x010ProfileListHead:_LIST_ENTRY[0x86de0d30-0x86de0d30]//基本都是空的+0x018DirectoryTableBase:0xbeda71e0//......
  • 孤儿进程和僵尸进程
     孤儿进程和僵尸进程是操作系统中两种不同的进程状态,它们有着不同的特征和产生原因。1.孤儿进程:-孤儿进程是指父进程退出或意外终止后,子进程仍然在操作系统中运行的情况。由于子进程的父进程已经不存在,操作系统将其托付给init进程(在Unix/Linux系统中是进程号为1的init进程......
  • 多线程下使用List中的subList和remove方法产生的 java.util.ConcurrentModificationEx
    在说多线程操作List之前,我们先看下单线程下产生的问题:单线程List<Integer>listA=newArrayList<>();listA.add(1);listA.add(2);listA.add(3);listA.add(4);listA.add(5);listA.add(6);for(Integera:listA){......
  • 打开、关闭、切换App以及清除App进程,操作so easy!
    此文章来源于项目官方公众号:“AirtestProject”版权声明:允许转载,但转载必须保留原链接;请勿用作商业或者非法用途#一、前言很多新手同学在写自动化测试脚本的时候,打开、关闭、切换App的方式还是使用最基础的方式,也有同学在交流群内多次询问是否有打开、关闭、切换App以及清除A......
  • 进程、线程和协程之间的区别和联系
    文章目录一、进程二、线程三、进程和线程的区别与联系四、一个形象的例子解释进程和线程的区别五、进程/线程之间的亲缘性六、协程一、进程进程,直观点说,保存在硬盘上的程序运行以后,会在内存空间里形成一个独立的内存体,这个内存体有自己独立的地址空间,有自己的堆,上级挂靠单......
  • python多进程中嵌入多进程注意事项
    例如代码:frommultiprocessingimportPoolp1=Pool(4)s=[1,2,3,4]foriins:p1.apply_asny(某方法,args=(i))p1.close()p1.join()此时,某方法中也有一个多进程设置,这样的话就是双重多进程,只要是传入的参数之间是没有关系的,那么就没有问题。如果此时,最外层的apply_......
  • 超线程/同步多线程(HT/SMT)技术
    超线程/同步多线程(HT/SMT)技术虽然现在超线程(Hyper-Threading)被大家广泛接受,并把所有一个物理核心上有多个虚拟核心的技术都叫做超线程,但这其实是Intel的一个营销名称。而实际上这一类技术的(学术/技术)通行名称是同步多线程(SMT,SimultaneousMultithreading)技术。SMT技术初衷是通......