linux查看python线程,Python多线程详解

线程概念:

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。线程可以分为两类:

内核线程:由操作系统内核创建和撤销。

用户线程:不需要内核支持而在用户程序中实现的线程。

全局解释性锁(GIL):

在讲Python多线程,有一个绕不开的东西,叫全局解释性锁(Global Interpreter Lock)。这东西导致了无论你启多少个线程,你有多少个cpu, Python在执行的时候同一时刻只允许一个线程运行。这就导致了大家对Python多线程的印象普遍就是‘鸡肋“。

需要注意的一点是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。

线程模块:

Python3 通过两个标准库 _thread 和 threading 提供对线程的支持。_thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的。threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:

threading.currentThread(): 返回当前的线程变量。

threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。

threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:

run(): 用以表示线程活动的方法。

start():启动线程活动。

join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。

isAlive(): 返回线程是否活动的。

getName(): 返回线程名。

setName(): 设置线程名。

Python threading模块:

(1)线程创建方式一:直接调用线程,创建Thread类,并传递一个需要多线程运行的函数。示例如下:

import threading

import time

def func(no):

time.sleep(2)

print("the thread number:%s"%no)

time_start = time.time()

thread_list = []

for i in range(10):

t = threading.Thread(target=func,args=(i,))  #生成线程实例

t.start()  #启动线程

thread_list.append(t)

for t in thread_list:

t.join()  #等待线程中止

time_end = time.time()

print("程序总共运行%d秒"%int(time_end-time_start))

#运行结果:

the thread number:4

the thread number:2

the thread number:5

the thread number:1

the thread number:3

the thread number:0

the thread number:7

the thread number:9

the thread number:6

the thread number:8

程序总共运行2秒

(2)线程创建方式二:继承式调用,创建一个Thread类的子类,并重写Thread类的run方法。示例如下:

import threading

import time

class TestThread(threading.Thread):

def __init__(self,no):

threading.Thread.__init__(self)

self.no = no

def run(self):  #重写父类Thread的run方法,改方法内定义每个线程要运行的程序代码

time.sleep(2)

print("the thread number:%s" % self.no)

for i in range(10):

t = TestThread(i)

t.start()

(3)守护进程:

import threading

import time

def run(i):

print("run({}) start".format(i))

time.sleep(2)

print("run({}) end".format(i))

def main():

for i in range(5):

t = threading.Thread(target=run,args=(i,))

t.start()

m = threading.Thread(target=main,args=())

m.setDaemon(False)

m.start()

m.join(timeout=1)

print("main thread end")

# m.setDaemon(True) 运行结果:

run(0) start

run(1) start

run(2) start

run(3) start

run(4) start

main thread end

# m.setDaemon(False) 运行结果:

run(0) start

run(1) start

run(2) start

run(3) start

run(4) start

main thread end

run(3) end

run(2) end

run(0) end

run(4) end

run(1) end

从上述示例中可以看出:将main线程设置为Daemon线程,它做为程序主线程的守护线程,当主线程退出时,m线程也会退出,由m启动的其它子线程会同时退出,不管是否执行完任务

(4)线程同步(线程锁):一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,很容易造成数据不同步。使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。示例如下:

import threading

import time

def add():

global num  #获取全局变量

time.sleep(1)

Lock.acquire()  #修改全局变量前获取锁(加锁)

num -= 1

Lock.release()  #修改后释放锁

Lock = threading.Lock()  #生成一个全局锁

num = 100  #设置一个共享数据

thread_list = []

for i in range(100):

t = threading.Thread(target=add,args=())

t.start()

thread_list.append(t)

for t in thread_list:

t.join()

print("final num:",num)

#运行结果:

在未加锁前结果不一定是 0

加锁后运行结果一定是 0

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值