Qu'est-ce qu'un processus ? Qu'est-ce qu'un fil ?

零下一度
Libérer: 2017-07-24 16:58:09
original
1868 Les gens l'ont consulté

Bases :

Qu'est-ce qu'un processus ?

La mémoire de chaque programme est indépendante, par exemple : le monde ne peut pas accéder à QQ.

Processus : QQ est exposé à la gestion du système d'exploitation dans son ensemble, qui comprend les appels à diverses ressources (gestion de la mémoire, appels d'interface réseau, etc.). Démarrer un QQ signifie démarrer un processus.

Qu'est-ce qu'un thread ?

Un thread est la plus petite unité que le système d'exploitation peut effectuer pour planifier des opérations. Le Thread est inclus dans le Process et constitue la véritable unité opérationnelle du processus.

Il doit y avoir au moins un thread dans un processus.

Un thread fait référence à un seul flux séquentiel de contrôle dans un processus.

Un processus CAS exécute plusieurs threads simultanément, chaque thread effectue différentes tâches en parallèle et les threads sont indépendants les uns des autres.

La différence entre les threads et les processus :

Processus : un ensemble de diverses ressources de gestion

Thread : la plus petite unité de planification du système d'exploitation, qui est un ensemble d'instructions

Relation :

Le premier thread du processus est le thread principal. Le thread principal crée d'autres threads. Les autres threads peuvent également créer des threads <.>

Un processus a un processus parent, un processus enfant, un espace mémoire indépendant, un identifiant de processus unique et un pid

Qu'est-ce que le changement de contexte ?

La commutation de contexte, également appelée commutation de processus ou commutation de tâches, fait référence au passage du processeur d'un processus ou d'un thread à un autre. Par exemple, comme suit :

a. Ouvrez QQ et WeChat, discutez d'abord sur QQ, puis passez à WeChat pour discuter, puis passez à QQ. Cette opération est appelée changement de contexte.

b. Ouvrez plusieurs applications en même temps. La configuration du processeur de l'ordinateur est à 4 cœurs. Lors du basculement entre plusieurs applications, il n'y a pas de décalage et vous ne ressentez pas du tout les tâches de commutation du processeur, car le processeur traite rapidement. . , il n'y a donc pas de décalage lors du basculement entre les applications

Fil unique :

import timeimport requestsdef get_res():
    urls = ['','','','']
    start = time.time()for url in urls:print(url)
        resp = requests.get(url)print(resp)
    end = time.time()print('单线程运行时间:', end - start)
Copier après la connexion
Résultat de l'exécution :

http://www.baidu.com<Response [200]>https://www.taobao.com/
<Response [200]>https://www.jd.com/
<Response [200]>http://www.meilishuo.com/
<Response [200]>单线程运行时间: 1.0470597743988037
Copier après la connexion
Explication :

a. Le processeur est demandé séquentiellement

b À moins que le processeur reçoive une réponse d'une URL, il ne demandera pas l'URL suivante.

c. Les requêtes réseau prennent beaucoup de temps, le CPU reste donc inactif en attendant le retour des requêtes réseau

Multi-threading :

import timeimport threadingdef run(count):#每次执行该方法,需要休息2stime.sleep(2)print(count)#开始创建多线程start = time.time()for i in range(5):#创建线程,指定运行哪个函数,也就是指定哪个函数运行需要创建多线程#target=要运行的函数名# args=函数运行传入的参数,run方法需要传入count,把创建th = threading.Thread(target=run, args=(i, ))#启动线程    th.start()#多线程创建完毕且运行结束end = time.time()print('运行时间:', end - start)
Copier après la connexion
Résultats d'exécution :

运行时间: 0.0
104
2
3
Copier après la connexion

Explication :

a. threads , car il faut attendre 2s avant de s'exécuter, donc le temps d'exécution du multi-threading est d'au moins 2s

Alors quel est le résultat imprimé ?

Le temps d'exécution imprimé est le temps d'exécution du thread principal, car lors de l'exécution d'un fichier python, si le multi-thread n'est pas démarré, au moins un thread est en cours d'exécution

Les threads sont indépendants les uns des autres. Le thread principal s'exécute initialement. Lorsque le threading.Thread est atteint, un thread est créé exécute la méthode de boucle et le thread principal effectue d'autres opérations

 

Le thread principal n'attend pas la fin des autres threads avant de se terminerb Les données de comptage imprimées ne sont pas ordonnées car multi-threads. run run La méthode ne consiste pas à faire la requête suivante une fois la première requête terminée, mais à créer un thread, puis à exécuter la méthode run, puis à créer un autre thread. Après quoi le thread est exécuté, le résultat sera imprimé

.

c. Un total de 5 threads ont été créés

Si vous souhaitez compter le temps total d'exécution des multi-threads, c'est-à-dire le temps depuis le début de la création du thread jusqu'à la fin du fil (vous n'avez pas besoin de considérer les différences entre les fils) en cours d'exécution), l'opération est la suivante :

join() wait (attendez que le fil se termine)

import timeimport threadingdef run(count):#每次执行该方法,需要休息2stime.sleep(2)print(count)#开始创建多线程start = time.time()#存放创建的所有线程threads_list = []for i in range(5):#创建线程,指定运行哪个函数,也就是指定哪个函数运行需要创建多线程#target=要运行的函数名# args=函数运行传入的参数,run方法需要传入count,把创建th = threading.Thread(target=run, args=(i, ))#启动线程    th.start()#把启动的每一个线程添加到线程组内    threads_list.append(th)for t in threads_list:#主线程循环等待每个子线程运行完毕, t代表每个子线程t.join()  #等待线程结束#多线程创建完毕且运行结束end = time.time()print('运行时间:', end - start)
Copier après la connexion
Résultat de l'exécution :

01
2
4
3运行时间: 2.0011146068573
Copier après la connexion
Thread démon

Thread démon : une fois le thread principal terminé, il se terminera indépendamment de la fin de l'exécution du fil démon. Par exemple :

Par exemple, l'empereur a de nombreux serviteurs. Lorsque l'empereur meurt, après la mort, tant de serviteurs ont dû être enterrés avec lui.

Tant que le thread non-démon se termine, que le thread démon se termine ou non, le programme se termine

GIL 全局解释器锁

例如 4核机器上 
Python创建4线程,四个线程均匀分到多核上,但是同时只能一核在处理数据。 
python调用操作系统、C语音的原生接口,在出口做了设置。全局解释器锁,保证数据统一 
所以有人说python的线程是假线程。 
在修改数据的时候,为了防止数据改乱了,所以多线程就变成串行处理,但是以为是python在处理,实际上是调用了操作系统的C语音的线程接口,所以中间的过程,python控制不了了,只知道结果。在这种情况下,设置的方式是出口控制,虽然四个线程,但是同一时间只有一个线程在工作。 
  
所以这算是python的一个缺陷,但是也不能说是python的缺陷,是Cpython的缺陷。因为Cpython是C语音写的,以后python的未来是PYPY。 

线程锁

线程锁,又叫互斥锁

线程之间沟通:保证同一时间只有一个线程修改数据

python2.x 中需要加锁,Python3.x中加不加锁都一样,因为解释器做了优化

import threadingfrom threading import Lock#创建lock对象num = 0
lock = Lock()   #申请一把锁,创建锁的对象def run2():global num
    lock.acquire()      #修改数据前 加锁num += 1lock.release()      #修改后释放解锁lis = []for i in range(5):#创建线程t = threading.Thread(target=run2)#启动线程    t.start()#将启动的线程添加到线程组内    lis.append(t)for t in lis:#等待线程运行结束    t.join()#num的值为5,执行多次后,会出现不一样的值print('over', num)
Copier après la connexion

RLock 递归锁

大锁中还有小锁、递归锁,解锁时就混了,所以用递归锁,Rlock()

import threading,timedef run1():print("grab the first part data")
    lock.acquire()global num
    num +=1lock.release()return numdef run2():print("grab the second part data")
    lock.acquire()global  num2
    num2+=1lock.release()return num2def run3():
    lock.acquire()
    res = run1()print('--------between run1 and run2-----')
    res2 = run2()
    lock.release()print(res,res2)if __name__ == '__main__':

    num,num2 = 0,0
    lock = threading.RLock()  # 声明递归锁# lock = threading.Lock() # 用互斥锁,会锁死了,弄混锁情况,可以试一下for i in range(10):
        t = threading.Thread(target=run3)
        t.start()while threading.active_count() != 1:print(threading.active_count())else:print('----all threads done---')print(num,num2)
Copier après la connexion

 多线程的另一种写法:

import threadingimport timeclass MyThread(threading.Thread):def __init__(self, num):
        threading.Thread.__init__(self)
        self.num = numdef run(self):  # 定义每个线程要运行的函数print("running on number:%s" % self.num)
        time.sleep(3)if __name__ == '__main__':
    t1 = MyThread(1)
    t2 = MyThread(2)
    t1.start()
    t2.start()
Copier après la connexion

多进程(了解即可):

python里面的多线程,是不能利用多核cpu的,如果想利用多核cpu的话,就得使用多进程

多进程适用CPU密集型任务

多线程适用io密集型任务

from multiprocessing import Processdef f(name):
    time.sleep(2)print('hello', name)if __name__ == '__main__':for i in range(10):
        p = Process(target=f, args=('niu',))
        p.start()
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!