当前位置: 首页 > news >正文

北京建设公司有哪些长沙seo咨询

北京建设公司有哪些,长沙seo咨询,上海好的高端网站建设服务公司,网站设计首页框架图片_thread是python标准库中的一个低层多线程API,可以在进程中启动线程来处理任务,并且提供了简单的锁机制来控制共享资源的同步访问。本文就_thread模块的用法和特性做个简单的演示。 文章目录 一、进程和线程的区别二、_thread模块的用法2.1 派生线程2.2…

_thread是python标准库中的一个低层多线程API,可以在进程中启动线程来处理任务,并且提供了简单的锁机制来控制共享资源的同步访问。本文就_thread模块的用法和特性做个简单的演示。

文章目录

  • 一、进程和线程的区别
  • 二、_thread模块的用法
    • 2.1 派生线程
    • 2.2 同步化访问控制
    • 2.3 子线程的退出控制
      • 2.3.1 通过sleep等待子线程运行结束
      • 2.3.2 通过锁的状态监测子进程结束
      • 2.3.3 通过共享变量监测子进程结束

一、进程和线程的区别

并行(多任务处理)是现代操作系统的基本特性,一个程序可以同时处理很多任务而不被阻塞。多任务处理的基本方式有两种:进程分支和线程派生。

进程分支就是从当前进程复制一个程序副本,程序中的内存副本,文件描述符等都会被复制,子进程改变一个全局对象只是修改本地的副本,不会影响到父进程。常用在启动独立的程序。

线程派生和进程分支类似,但是子线程依然在原进程中运行,所有的子线程都会共享进程中的全局对象,相对于进程分支,少了一个"复制"的操作,因此更加轻量化,且由于共享进程对象,相当于自带了线程间的通信机制(进程间的通信则需要借助管道,套接字,信号等外部工具)。常用在处理一些轻量级任务。

但这些共享对象的访问可能出现冲突,_thread也提供了锁机制来同步化对象访问,例如修改一个对象时,先获取锁,完成后再释放,这样就可以保证任意时间点,最多能有1个线程能修改这个共享对象,防止出现混乱。

二、_thread模块的用法

_thread模块中的start_new_thread可以开启一个新的线程并运行指定程序。

2.1 派生线程

当程序启动时,其实它就已经启动了一个线程,这个就是主线程。通过_thread.start_new_thread方法,传入一个函数对象和一个参数元组,就可以开启新线程来执行所传入的函数对象。简单的演示如下:

import _thread as threaddef func(id):print('我是 {} 号子线程'.format(id))for i in range(5):thread.start_new_thread(func,(i,))

在这里插入图片描述

上面代码执行示意图如下:for循环执行了5次start_new_thread,这会开启5个线程,每个线程去执行func函数。因为线程是并行的,所以输出的顺序并不是0,1,2,3,4而是混乱的。注意3,4号子线程打印出现了重叠,这是因为它们共享一个标准输出流,而我们没有做同步化访问控制,因而它们同时打印输出。
在这里插入图片描述

2.2 同步化访问控制

由于子线程可以共享进程中的资源,这既是一个优势(方便线程间通信),也带来了共享资源访问的问题,如果多个子线程同时修改一个共享资源,那么就容易出现冲突,例如上面的输出重叠。

为了解决这类问题,_thread模块中的allocate_lock方法提供了一个简单的锁机制来控制共享访问,每次获取共享资源时先获取锁,可以保证任何时间点最多只有1个线程可以访问该资源。示例如下:

import _thread as threadlock = thread.allocate_lock()    # 定义一个锁def func(id):with lock:    # 用上下文管理器自动控制锁的获取和释放print('我是 {} 号子线程'.format(id))for i in range(5):thread.start_new_thread(func,(i,))

在这里插入图片描述

with lock会自动管理锁对象的获取和释放,默认线程会一直等待直到锁的获取,如果想要更精细的控制可以使用下面的方式:

lock.acquire()    # 获取锁
print('我是 {} 号子线程'.format(id))
lock.release()    # 释放锁

lock.acquire()有2个可选的参数:blocking=True代表无法获取锁时等待,blocking=False代表如无法立刻获取锁则返回。timeout=-1代表等待的秒数(-1代表无限等待),此参数只有在blocking设置为True时才能指定。

2.3 子线程的退出控制

_thread派生子线程后,如果主线程运行完毕,而子线程依然在运行中,那么所有子线程就会随着主线程的退出而被终止。

我们在子进程中增加一个sleep来模拟长时间任务,让其运行时长超过主线程。将下面的代码保存到一个thread1.py中,以一个独立进程启动:

import _thread as thread, timelock = thread.allocate_lock()    # 定义一个锁def func(id):time.sleep(id)    # 子线程会睡眠,运行时长将超过主线程with lock:print('我是 {} 号子线程'.format(id))for i in range(5):thread.start_new_thread(func,(i,))print('主线程结束,退出...')    # 主线程退出时打印提示

在这里插入图片描述

可以看到,主线程打印了退出提示,但子线程却没有任何输出,这是因为主线程运行的时间非常短,当其退出时,所有子线程都终止了。这种情况显然不是我们想看到的。示例图如下:
在这里插入图片描述

2.3.1 通过sleep等待子线程运行结束

为了解决上面的问题,一个简单的解决方案可以在主线程中加一个sleep,让其等待一段时间再退出,但这个时间我们只能预估。在上面的代码基础上,增加一个time.sleep(3),让主线程退出前等待3秒,保存为thread2.py,再次执行:

import _thread as thread, timelock = thread.allocate_lock()    # 定义一个锁def func(id):time.sleep(id)    # 子线程会睡眠,运行时长将超过主线程with lock:print('我是 {} 号子线程'.format(id))for i in range(5):thread.start_new_thread(func,(i,))time.sleep(3)    # 主线程等待3秒再退出
print('主线程结束,退出...')    # 主线程退出时打印提示

在这里插入图片描述
可以看到部分子进程运行完毕,但还有部分子进程未完成,因此这种方法不是很准确,虽然你可以给一个足够长的时间来保证所有子进程运行结束,但如果进程长时间不结束,也会占用系统资源。

2.3.2 通过锁的状态监测子进程结束

_thread.allocate_lock除了可以控制共享对象的访问,还可以用来传递全局状态,下面定义了包含5把锁的列表,每个子线程执行完成后会去获取其中对应位置上的锁,在主线程中通过lock.locked()来检查是否所有的锁都被获取,当所有锁都被获取时(代表所有子线程都结束),主线程退出。将下面代码保存到thread3.py中,再次运行:

import _thread as thread, timelock = thread.allocate_lock()    # 定义一个锁
exit_locks = [thread.allocate_lock() for I in range(5)]   # 定义一个列表,包含5把锁,对应稍后启动的5个子线程def func(id):time.sleep(id)    # 子线程会睡眠,运行时长将超过主线程with lock:print('我是 {} 号子线程'.format(id))exit_locks[id].acquire()    # 执行完成后获取exit_locks中对应位置的锁for i in range(5):thread.start_new_thread(func,(i,))for lock in exit_locks:while not lock.locked(): pass    # lock.locked()检测锁是否已被获取print('主线程结束,退出...')    # 主线程退出时打印提示

在这里插入图片描述
测试时可以发现,主线程会在所有子线程执行完毕后立刻退出,即不会提前导致子线程终止,也不会推迟浪费系统资源。

2.3.3 通过共享变量监测子进程结束

由于子线程可以共享进程中的变量,因此子线程中对共享对象的修改在主线程也可以看到,我们可以将上面的锁替换为简单的变量,可以达到相同的效果,下面使用一个共享列表,通过在子线程中修改变量值传递状态,将下面代码保存为thread4.py并执行:

import _thread as thread, timelock = thread.allocate_lock()    # 定义一个锁
exit_flags = [False]*5   # 定义一个全局共享列表,包含5个布尔变量Falsedef func(id):time.sleep(id)    # 子线程会睡眠,运行时长将超过主线程with lock:print('我是 {} 号子线程'.format(id))exit_flags[id] = True    # 执行完成后将共享列表中对应位置的值改为Truefor i in range(5):thread.start_new_thread(func,(i,))while False in exit_flags:pass    # 检测列表中是否有False,如果全部为Ture,代表所有子线程执行完毕print('主线程结束,退出...')    # 主线程退出时打印提示

在这里插入图片描述
可以看到主线程会等待子线程执行完毕后退出,这种方式相比上面可以节约锁分配的资源,看上去也更加简单。

以上即是_thread模块的基本用法。基于_thread模块还有高级的threading模块,_threading模块是基于类和对象的高级接口,并提供了额外的控制工具,例如threading.join()可以实现等待子进程退出。

http://www.dinnco.com/news/39089.html

相关文章:

  • 使用局域网做网站网站建设开发公司
  • 环江住房和城乡建设部网站中国北京出啥大事了
  • bms营销方法亚马逊seo是什么意思
  • 企业网站建设注意事项湖南长沙最新疫情
  • 石家庄网站系统开发网络推广公司方案
  • 美食网页设计模板素材seo网站优化服务
  • 物流网站开发短信广告投放软件
  • 嘉兴网站建设系统在哪个网站可以免费做广告
  • 行业网站 源码关键词词库
  • 环保设备网站建设模板如何优化seo
  • 网站换模板对seo动态网站建设
  • pr模板网网站关键词优化排名软件系统
  • 河北网站开发费用百度站长工具怎么关闭教程视频
  • 网站开发前端库网络营销名词解释
  • 想开一个做网站的公司aso关键词覆盖优化
  • 自己做网站怎么连接外网seo推广有哪些方式
  • 上海专门做网站的公司做百度推广代运营有用吗
  • 武汉大学人民医院研究生院长沙网站seo技术厂家
  • 旅游网站建设的意义北京seo招聘网
  • 驻马店做网站优化公司网站搭建流程
  • 网站建设找哪家抖音seo推广外包公司好做吗
  • 写的网站怎么做接口杭州市优化服务
  • 福田商城网站建设全球搜索引擎市场份额
  • canvas设计网站搜索引擎优化的英文
  • 河南住房建设部网站网页平台做个业务推广
  • 可以做热图的在线网站2345网址导航主页
  • 如何与导航网站做友情链接b站视频推广怎么买
  • 哪个网站找做软件下载seo优化师是什么
  • 可以货代从哪些网站开发客户企业文化设计
  • 广告设计是干什么的最优化方法