加入收藏 | 设为首页 | 会员中心 | 我要投稿 安卓应用网 (https://www.0791zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python基础学习20----线程

发布时间:2020-05-25 03:32:06 所属栏目:Python 来源:互联网
导读:什么是线程 线程,有时被称为轻量进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中

Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。线程是程序中一个单一的顺序控制流程。进程内有一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指令运行时的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。

  进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

线程与进程的关系

<span style="color: #0000ff;">def<span style="color: #000000;"> func(msg):
<span style="color: #0000ff;">print<span style="color: #000000;">(msg)
<span style="color: #0000ff;">print(<span style="color: #800000;">"<span style="color: #800000;">这是一个线程<span style="color: #800000;">"<span style="color: #000000;">)

t=threading.Thread(target=func,args=(<span style="color: #800000;">"<span style="color: #800000;">hello world<span style="color: #800000;">"<span style="color: #000000;">,))
t.start()

通过继承类的方式创建线程

==</span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; run(self): </span><span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;这里是将threading.Thread中的run方法进行了重载</span> <span style="color: #0000ff;"&gt;print</span>(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;%s is %d</span><span style="color: #800000;"&gt;"</span>%<span style="color: #000000;"&gt;(self.name,self.age))

t=Mythread(<span style="color: #800000;">"<span style="color: #800000;">sfencs<span style="color: #800000;">",19<span style="color: #000000;">)
t.start()

2.线程的并发

单个线程的创建基本没有意义,只是与主线程并发,现在我们看一下多个线程的并发

===</span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; run(self): </span><span style="color: #0000ff;"&gt;print</span><span style="color: #000000;"&gt;(self.name) time.sleep(self.second) </span><span style="color: #0000ff;"&gt;print</span><span style="color: #000000;"&gt;(self.age)

t1=Mythread(<span style="color: #800000;">"<span style="color: #800000;">sfencs<span style="color: #800000;">",19,2<span style="color: #000000;">)
t2=Mythread(<span style="color: #800000;">"<span style="color: #800000;">Tom<span style="color: #800000;">",25,5<span style="color: #000000;">)
t1.start()
t2.start()

这里先同时打印sfencs和Tom,过了两秒打印19,又过3秒打印25.这说明这两个线程是并发的,如果是串行的那么会使用7秒完成

我们可以使用time模块计算时间

===</span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; run(self): </span><span style="color: #0000ff;"&gt;print</span><span style="color: #000000;"&gt;(self.name) time.sleep(self.second) </span><span style="color: #0000ff;"&gt;print</span><span style="color: #000000;"&gt;(self.age)

time_begin=<span style="color: #000000;">time.time()

t1=Mythread(<span style="color: #800000;">"<span style="color: #800000;">sfencs<span style="color: #800000;">",5<span style="color: #000000;">)
t1.start()
t2.start()
time_end=<span style="color: #000000;">time.time()
<span style="color: #0000ff;">print(time_end-time_begin)
'''

sfencsTom0.00103068351745605471925

'''

这里出现一个问题,输出的时间是0.0010306835174560547,而且在年龄之前输出的

原因是计算时间的代码属于主线程,它与两个自己创建的线程并发,所以它提前完成了计算,为了解决这个办法,我们使用join()方法

3.join()

time_begin=t1=Mythread(<span style="color: #800000;">"<span style="color: #800000;">sfencs<span style="color: #800000;">",5<span style="color: #000000;">)
t1.start()
t2.start()
t1.join()
t2.join()
time_end=<span style="color: #000000;">time.time()
<span style="color: #0000ff;">print(time_end-<span style="color: #000000;">time_begin)
<span style="color: #800000;">'''<span style="color: #800000;">
sfencs
Tom
19
25
5.001618146896362
<span style="color: #800000;">'''

这样就显然的看出程序并发节约了约2秒钟

除此之外join()方法还有一个参数为阻塞的时间,默认为一直阻塞

4.IO密集型任务和计算密集型任务

IO密集型任务就如上述的例子一样,有阻塞的状态,如sleep()或者等待相关信息,信号时会停用cpu的任务。IO密集型的任务在python中使用多线程能够很好的节约时间完成并发。

计算密集型任务没有等待状态,从上到下执行,没有任何等待

一个线程

</span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; run(self): i</span>=<span style="color: #000000;"&gt;0 </span><span style="color: #0000ff;"&gt;while</span> i<100000000<span style="color: #000000;"&gt;: i</span>+=1<span style="color: #000000;"&gt;

time_begin=<span style="color: #000000;">time.time()
t1=<span style="color: #000000;">Mythread()
t1.start()
t1.join()
time_end=<span style="color: #000000;">time.time()
<span style="color: #0000ff;">print(time_end-time_begin)#6.194466590881348

两个线程

</span><span style="color: #0000ff;"&gt;def</span><span style="color: #000000;"&gt; run(self): i</span>=<span style="color: #000000;"&gt;0 </span><span style="color: #0000ff;"&gt;while</span> i<100000000<span style="color: #000000;"&gt;: i</span>+=1<span style="color: #000000;"&gt;

time_begin=<span style="color: #000000;">time.time()
t1=<span style="color: #000000;">Mythread()
t2=<span style="color: #000000;">Mythread()
t1.start()
t2.start()
t1.join()
t2.join()
time_end=<span style="color: #000000;">time.time()
<span style="color: #0000ff;">print(time_end-time_begin)#11.998910427093506

可见计算密集型任务在python中并发并不能很好的节约时间,和串行差不多(在python以前版本中时间还会比串行多)

可是又有一个问题,我们的电脑不是有多核cpu吗,为什么不能同时两个cpu每个运行一个线程,那样时间就只有串行的一半啊?原因就是接下来讲的GIL

5.GIL

  首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可执行代码。有名的编译器例如GCC,INTEL C++,Visual C++等。Python也一样,同样一段代码可以通过CPython,PyPy,Psyco等不同的Python执行环境来执行。像其中的JPython就没有GIL。然而因为CPython是大部分环境下默认的Python执行环境。所以在很多人的概念里CPython就是Python,也就想当然的把GIL归结为Python语言的缺陷。所以这里要先明确一点:GIL并不是Python的特性,Python完全可以不依赖于GIL。

那么CPython实现中的GIL又是什么呢?GIL全称Global Interpreter Lock为了避免误导,我们还是来看一下官方给出的解释:

(编辑:安卓应用网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读