线程

1. 什么是线程

线程就是进程里面的执行单位,每一个进程肯定都自带一个线程,真正被cpu执行的是线程,线程是代码的执行过程,该过程中需要的资源都找对应的进程要

进程是资源的单位,线程是执行单位!
image

补充:同一个进程里面的多个线程资源是共享的!

2. 为啥要有线程

一个进程里面可以开设多个线程,而开设线程是不需要申请内存空间的(进程需要),因此,开设线程的消耗远远小于进程!

3. 如何使用线程

3.1 创建线程的第一种方式(掌握)

from threading import Thread # 导入线程模块
from multiprocessing import Process
import time

# 定义子线程函数
def func(name):
    print('%s 来啦'%name)
    time.sleep(2)
    print('%s走了'%name)

# 创建线程不需要写在main下,但是我们还是习惯性的把它写在main下
if __name__ == '__main__':
    # 创建线程对象
    t = Thread(target=func,args=('zhang',))
    # p = Process(target=func,args=('zhang',))
    # p.start()
    t.start() # 启动线程
    # 线程和进程的开启相比,线程更加的块,线程不需要开辟内存空间
    print('主')

3.2 创建线程的第二种方式

from threading import Thread

# 1.创建一个类,该类继承线程类
class MyThread(Thread):
    # 第二种方法需要给子线程添加参数的方法是类中有一个双init方法
    # 先继承父类的双init方法,然后在书写需要自己加入的参数,这样就可以在run函数里调用参数了
    def __init__(self,name):
        super().__init__()
        self.name = name
    # 2.该类中子线程函数名必须是run
    def run(self):
        print('我是线程%s'%self.name)

if __name__ == '__main__':
    # 3.创建子线程对象
    t = MyThread('zhang')
    # 4.开启子线程
    t.start()
    print('主')

3.3 线程中的join方法

join方法的含义是:主线程等待子线程运行完毕再执行

from threading import Thread # 导入线程模块
from multiprocessing import Process
import time

def func(name):
    print('%s 来啦'%name)
    time.sleep(1)
    print('%s走了'%name)

if __name__ == '__main__':
    t = Thread(target=func,args=('zhang',))
    t.start()
    t.join() # join方法的含义是:主线程等待子线程运行完毕再执行
    print('主')

3.4 线程对象和其他方法

from threading import Thread,active_count,current_thread
import time,os

def func():
    # os.getpid()获取当前线程的进程id,主线程和子线程id相同
    # print('hello',os.getpid())
    # current_thread().name获取当前线程的线程名
    print('hello', current_thread().name)
    time.sleep(2)

if __name__ == '__main__':
    t = Thread(target=func)
    t.start()
    # print('主',current_thread().name)
    # active_count() 获取当前活跃的线程数量
    print('主',active_count())

3.5 守护线程

from threading import Thread
import time

def func(name):
    print('%s来啦'%name)
    time.sleep(2)
    print('%s走了'%name)

if __name__ == '__main__':
    t = Thread(target=func,args=('zhang',))
    t.daemon = True # 守护主线程,主线程结束之后该子线程也会结束
    t.start()
    print('主')
    """
    主线程一般不会自动结束,它会等待所有非守护线程结束之后再结束
    因为主线程结束意外着主进程也结束了,这样其他线程就无法调用主进程的资源了
    """

3.6 线程的互斥锁

from threading import Thread,Lock
import time

momey = 100
# 加一把锁
metua = Lock()

def func():
    global momey
    # 在获取数据的前面加一把锁
    metua.acquire()
    num = momey
    time.sleep(0.01)
    momey = num -1
    # 释放该锁
    metua.release()

if __name__ == '__main__':
    t_list = []
    for i in range(100):
        t = Thread(target=func)
        t.start()
        t_list.append(t)
    for t in t_list:
        t.join()
    print(momey)

3.7 GIL锁与互斥锁

GIL需要知道的重点:

	1.GIL不是python的特点而是CPython解释器的特点
	2.GIL是保证解释器级别的数据的安全
	3.GIL会导致同一个进程下的多个线程的无法同时执行即无法利用多核优势(******)
	4.针对不同的数据还是需要加不同的锁处理 
	5.解释型语言的通病:同一个进程下多个线程无法利用多核优势

GIL锁与互斥锁的区别

from threading import Thread,Lock
import time

momey = 100
# 加一把锁
metua = Lock()

def func():
    global momey
    # 在获取数据的前面加一把锁
    metua.acquire()
    num = momey
    time.sleep(0.01) # 注意:这里sleep是在模拟网络延迟。如果假设没有网络延迟,没有互斥锁LOCK,得到money的结果也应为0,因为一个进程里有一个cpython解释器,cpython解释器有一个GIL锁的概念,同一个进程下的多个线程无法同时执行,它们必须去抢同一个GIL锁,没有网络延迟(没有IO),GIL锁就会直到数据操作完在释放,保证了多个线程执行的数据安全;但是实际上是有网络延迟的,就比如sleep,这时GIL锁就会直接释放掉,导致得到的money=99
    momey = num -1
    # 释放该锁
    metua.release()

if __name__ == '__main__':
    t_list = []
    for i in range(100):
        t = Thread(target=func)
        t.start()
        t_list.append(t)
    for t in t_list:
        t.join()
    print(momey)

3.8多线程与多进程的比较

当需要处理的工作大都是是计算密集型时优先考虑多进程(较好的利用多核优势)
当需要处理的工作大都是IO密集型时优先考虑多线程(节省空间消耗)

计算密集型就是计算处理偏多
IO密集型就是用户输入输出偏多

# 当处理的工作是计算密集型的时候,好像现在多线程比多进程有优势???待验证!
from multiprocessing import Process
from threading import Thread
import os,time

def work():
    res = 0
    for i in range(1000000):
        res *= i

if __name__ == '__main__':
    list = []  # 将下面for循环每次开设的线程/进程对象存储起来
    print(os.cpu_count()) # 获取当前计算机的CPU个数
    start_time = time.time()  # 获取开始时间
    for i in range(16): # for循环开设进程/线程
        # p = Process(target=work)
        p = Thread(target=work)
        p.start()
        list.append(p) # 将每次开设的进程对象添加到列表里
    for p in list: # 变量进程对象
        p.join() # 守护主进程/线程
    print(time.time()-start_time)
    # 计算密集型 多进程用时1.8412911891937256秒  多线程用时0.318603515625秒

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:线程 - Python技术站

(0)
上一篇 2023年4月2日
下一篇 2023年4月2日

相关文章

  • xadmin的使用

    安装 在项目的虚拟环境下执行 pip install https://codeload.github.com/sshwsfc/xadmin/zip/django2 注意:xadmin对于不同django版本有不同的版本,一定要使用相对应的版本 在app中注册 INSTALLED_APPS = [ # … # xadmin主体模块 ‘xadmin’, # …

    Python开发 2023年4月2日
    00
  • for循环语法

    for循环 for循环常用来遍历取值! for循环的基本语法 for 变量名 in 可迭代对象: 代码1 代码2 … # 可迭代对象可以是字典、列表、字符串、元组、集合 for + range range是用来控制for循环次数的方法 for i in range(1,9): print(‘====’) # range(1,9)循环1-8次,括号是顾头不…

    Python开发 2023年4月2日
    00
  • input与print语法

    1.input输入语法 input是用来接收用户输入的一种语法,实现计算机与用户之间的交互,改方法有一个返回值,返回的是用户输入的字符串! 语法:res = input(‘请输入您的账号:’) 在python3中,用户输入的数据类型将会被全部转成字符串类型。在python2中,用户输入什么数据类型,程序就会转成什么类型,指的注意的是,用户假如输入的数据类型错…

    Python开发 2023年4月2日
    00
  • rest_framework认证源码分析

    认证源码分析 位置 : APIVIew—-》dispatch方法—》self.initial(request, *args, **kwargs)—->有认证,权限,频率三个版块 分析: 只读认证源码: self.perform_authentication(request)—》self.perform_authentication(re…

    2023年4月2日
    00
  • django中视图函数的FBV和CBV

    1.什么是FBV和CBV FBV是指视图函数以普通函数的形式;CBV是指视图函数以类的方式。 2.普通FBV形式 def index(request): return HttpResponse(‘index’) 3.CBV形式 3.1 CBV形式的路由 path(r’^login/’,views.MyLogin.as_view()) 3.2 CBV形式的视图…

    Python开发 2023年4月2日
    00
  • 操作系统启动流程和BIOS介绍

    1.BIOS介绍 我们刚刚买回来的电脑裸机是可以直接启动的,这是由于生产厂商在电脑出厂的时候就在电脑里编写了一个只可读的系统功能BIOS,该系统被写入了ROM(只读内存中) BIOS是一个过渡性的操作系统,当安装了window等其他操作系统时,该系统会被快速的代替 2.操作系统的启动流程 1.计算机通电2.BIOS开始运行,检测硬件:cpu、内存、硬盘等3.…

    2023年4月2日
    00
  • 数据库配置限)不用root用户操作数据库了(为数据库创建用户,并赋予权限)

    步骤 1.为路飞项目创建数据库 在mysql终端输入以下代码: create database luffy charset=utf8; 2.创建数据库用户 create user ‘username’@’host’ identified by ‘password’; 其中username为自定义的用户名;host为登录域名,host为’%’时表示为 任意IP…

    Python开发 2023年4月2日
    00
  • django中有关ajax的部分

    Django_ajax 1 简介 AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求; 异步交互:客户…

    Python开发 2023年4月2日
    00
合作推广
合作推广
分享本页
返回顶部