python 多线程

python 的标准库,提供了两个线程模块,分别为 _thread 和 threading 模块,_thread 为低端模块,threading为高端模块,对_thread进行了分装,大多数情况下,我们只用到 threading 模块。

启动一个线程,就是把一个函数传入,并创建一个Thread实例,然后调用 start() 函数开始执行。

例子如下:

import threading
import time

def worker():
    print("thread %s is running..." % threading.current_thread().name)
    n =0
    while n <5:
        n += 1
        print("thread %s >>>>%s" %(threading.current_thread().name,n))
        time.sleep(1)
    print("thread %s end" % threading.current_thread().name)
print("thread %s is running" % threading.current_thread().name)
t = threading.Thread(target = worker, name = 'WorkerThread')
t.start()
t.join()
print("thread %s end" %threading.current_thread().name)

运行结果如下:

thread MainThread is running
thread WorkerThread is running...
thread WorkerThread >>>>1
thread WorkerThread >>>>2
thread WorkerThread >>>>3
thread WorkerThread >>>>4
thread WorkerThread >>>>5
thread WorkerThread end
thread MainThread end

由于任何进程都会默认启动一个线程, 我们把该线程成为主线程,主线程又会启动新的线程,python的threading 模块有个current_thread()函数,它永远返回当前线程的实例。主线程实例的名字叫MainThread,子线程的名字在创建时指定,我们用WorkerThread命名子线程。 名字仅仅在打印时使用,完全没有其他意义。如果不起名字 python就会自动给线程命名为Thread-1, Thread-2.。。。

Lock() 锁

多线程和多进程的最大区别在于,多进程中,同一个变量,各自有一份拷贝在于每个进程中,互补影响,而多线程中,所有变量都有所有线程共享,所以任何一个变量都可以被任何一个线程修改。因此,线程之间共享数据的最大的危险在于多个线程同时修改一个变量,把内容给改乱了。之所以会改乱,是因为进程的调度是有操作系统完成的,当线程交替进行,就有可能把数据改乱。

为了避免这个问题,可以使用在每个以需要一个线程操作的地方 加上一把锁即可,创建一把锁,就是通过threading.Lock()实现。

实例如下:

balance = 0
lock = threading.Lock()

def run_thread(n):
    for i in range(100000):
        # 先要获取锁:
        lock.acquire()
        try:
            # 放心地改吧:
            change_it(n)
        finally:
            # 改完了一定要释放锁:
            lock.release()

当多个线程同时执行 lock.acquire()函数时,只有一个线程能够成功获得锁,其他线程就只能等待,知道获取锁

注意: 获得锁线程用完锁后一定要释放锁即lock.release(), 这样其他线程才不会一直等待,变成死线程。所以我们使用try..finally 来确保锁一定会被释放

多核cpu

启动与cpu数量相同的线程:

import threading

def loop():
    x = 0
    while True:
        x = x + 1
for i in range(threading.cpu_count()):
    t = threading.Thread(target = loop)
    t.start()

会发现,在4核CPU上可以监控到CPU占用率仅有102%,也就是仅使用了一核。这是因为 因为Python的线程虽然是真正的线程,但解释器执行代码时,有一个GIL锁:Global Interpreter Lock,任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。

Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值