美文网首页
【第54天】python全栈从入门到放弃

【第54天】python全栈从入门到放弃

作者: 36140820cbfd | 来源:发表于2019-08-24 20:05 被阅读0次

1 什么是线程?

线程被称作轻量级的进程,对于线程来说,因为有了GIL,所以没有真正的并行,那么什么是GIL呢,GIL:全局解释锁(只有Cpython解释器才有)

计算机的执行单位以线程为单位,线程是计算机的最小可执行单位。

进程是资源分配的基本单位,线程是可被调度的基本单位。

线程不可以拥有独立的资源,线程的执行,必须依赖进程的资源。

一个进程中,必须有一个线程。

进程由 代码段 数据段 PCB组成(process control block)
线程由 代码段 数据段 TCB组成(thread control block)

线程又分为用户级线程和内核级线程(了解)
用户级线程:对于程序员来说的,这样的线程完全被程序员控制执行,调度
内核级线程:对于计算机内核来说的,这样的线程完全被内核控制调度。

2 线程和进程的关系又是什么?

thread - 线程
import thread 操作线程的模块
import threading 用这个去操作线程
(1) cpu切换进程要比cpu切换线程 慢很多
在python中,如果IO操作过多的话,使用多线程最好了
(2) 在同一个进程内,所有线程共享这个进程的pid,也就是说所有线程共享所属进程的所有资源和内存地址
(3) 在同一个进程内,所有线程共享该进程中的全局变量

(4) 因为有GIL锁的存在,在Cpython中,没有真正的线程并行。但是有真正的多进程并行
当你的任务是计算密集的情况下,使用多进程好
总结:在CPython中,IO密集用多线程(快),计算密集用多进程

(5)关于守护线程和守护进程的事情(注意:代码执行结束并不代表程序结束)
守护进程:要么自己正常结束,要么根据父进程的代码执行结束而结束
守护线程:要么自己正常结束,要么根据父线程的执行结束而结束,注意不是跟随父进程代码结束而结束

3 主线程会随着子线程的结束而结束,守护线程会随着主线程的结束而结束,所以顺序是:子线程先结束,然后主线程结束,然后守护线程结束

代码块

from threading import Thread
from multiprocessing import Process
import time

def func():
    time.sleep(2)
    print(123)

def func1():
    time.sleep(1)
    print('abc')

# 守护线程是根据主线程执行结束才结束
# 守护线程不是根据主线程的代码执行结束而结束
# 主线程会等待普通线程执行结束,再结束
# 守护线程会等待主线程结束,再结束
# 所以,一般把不重要的事情设置为守护线程
# 守护进程是根据主进程的代码执行完毕,守护进程就结束
if __name__ == '__main__':
    t = Process(target=func)
    t.daemon = True    #设置为守护进程
    t.start()   #守护线程开启
    t1 = Process(target=func1)   
    t1.start()
    print(99999999999999999999)

4 开启线程的两种方法

4-1第一种方法:

代码块
import threading
from threading import Thread
import time

def func():
    print('这是一个子线程')
    time.sleep(2)

if __name__ == '__main__':
    t = Thread(target=func,args=())
    t.start()

4-2利用继承开启第二种方法:

代码块
import threading
import time
from threading import Thread

class Mythread(Thread):
    def __init__(self):
        super(Mythread,self).__init__()

    def run(self):
        print('我是一个线程')


m=Mythread()
m.start()   #我是一个线程

5 进程和线程的对比

5-1 对比1:用线程和进程同时开启100个任务,看谁快

代码块
from multiprocessing import Process  #导入进程
from threading import Thread   #导入线程
import time

def func():
    pass

if __name__ == '__main__':
    start = time.time()
    for i in range(100):
        p = Process(target=func)
        p.start()
    print('开100个进程的时间:',time.time() - start)

    start = time.time()
    for i in range(100):
        p = Thread(target=func)
        p.start()
    print('开100个线程的时间:', time.time() - start)

开100个进程的时间: 6.703976392745972
开100个线程的时间: 0.16490411758422852


5-2:子线程的pid和子进程的pid

代码块
from multiprocessing import Process
from threading import Thread
import time,os

def func(name):
    print('我是一个%s,我的pid是%s'%(name,os.getpid()))


if __name__ == '__main__':

    print('我是main,我的pid是%s'%(os.getpid()))
    for i in range(10):
        p = Process(target=func,args=('进程',))
        p.start()

    for i in range(10):
        p = Thread(target=func,args=('线程',))
        p.start()

#输出结果:

线程的pid都是6740,和main是一致的,进程的pid各种各样
我是main,我的pid是6740
我是一个进程,我的pid是16156
我是一个进程,我的pid是2540
我是一个进程,我的pid是10508
我是一个进程,我的pid是15600
我是一个进程,我的pid是204
我是一个进程,我的pid是13804
我是一个线程,我的pid是6740
我是一个线程,我的pid是6740
我是一个进程,我的pid是11104
我是一个线程,我的pid是6740
我是一个线程,我的pid是6740
我是一个线程,我的pid是6740
我是一个线程,我的pid是6740
我是一个线程,我的pid是6740
我是一个线程,我的pid是6740
我是一个线程,我的pid是6740
我是一个线程,我的pid是6740
我是一个进程,我的pid是13288
我是一个进程,我的pid是15516
我是一个进程,我的pid是11016

5-3 :用线程修改全局变量

代码块
from multiprocessing import Process
from threading import Thread,Lock
import time,os

def func():
    global num
    num-=1

if __name__ == '__main__':
    num = 100
    t_l = []
    for i in range(100):
        t = Thread(target=func)
        t.start()
        t_l.append(t)
    # time.sleep(1)
    [t.join() for t in t_l]
    print(num)
别跑,点个赞再走

相关文章

网友评论

      本文标题:【第54天】python全栈从入门到放弃

      本文链接:https://www.haomeiwen.com/subject/wniqectx.html