博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多线程、互斥锁、异步、GIL
阅读量:4567 次
发布时间:2019-06-08

本文共 4065 字,大约阅读时间需要 13 分钟。

多线程-threading

python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便被使用

 

from threading import Threadimport timedef test():    print("---1---")    time.sleep(1)for i in range(5):    t = Thread(target=test)    t.start()

  输出

---1------1------1------1------1---

  主线程等待子线程都执行完后才退出

使用thread子类创建线程

import threadingimport timeclass MyThread(threading.Thread):    def run(self):        msg = "I'm" + self.name + " @ " + str(i) # self.name是当前线程的名字        print(msg)        time.sleep(1)for i in range(5):    t = MyThread()    t.start()

  输出

I'm Thread-1 @ 0I'm Thread-2 @ 1I'm Thread-3 @ 2I'm Thread-4 @ 3I'm Thread-5 @ 4

  

线程的执行顺序

import threadingimport timeclass MyThread(threading.Thread):    def run(self):        for i in range(3):            msg = "I'm " + self.name + " @ " + str(i) # self.name是当前线程的名字,也可以用threading.current_thread().name获取当前线程的名字            print(msg)            time.sleep(1)for i in range(5):    t = MyThread()    t.start()

  输出

I'm Thread-1 @ 0I'm Thread-2 @ 0I'm Thread-3 @ 0I'm Thread-4 @ 0I'm Thread-5 @ 0I'm Thread-1 @ 1I'm Thread-3 @ 1I'm Thread-2 @ 1I'm Thread-5 @ 1I'm Thread-4 @ 1I'm Thread-1 @ 2I'm Thread-2 @ 2I'm Thread-3 @ 2I'm Thread-5 @ 2I'm Thread-4 @ 2

  

 线程共享全局变量

from threading import Threadimport timeg_num = 100def test1():    global g_num    for i in range(3):        g_num += 1    print("---in test1, g_num is %d---"%g_num)def test2():    global g_num    print("---in test2, g_num is %d---" % g_num)print("---线程创建之前g_num is %d---"%g_num)t1 = Thread(target=test1)t1.start()time.sleep(1)t2 = Thread(target=test2)t2.start()

  输出

---线程创建之前g_num is 100------in test1, g_num is 103------in test2, g_num is 103---

  

互斥锁

#创建锁

mutex = threading.Lock()
#锁定
mutex.acquire([blocking])
#释放
mutex.release()

 

当多个线程要修改同一个全局变量时,要用互斥锁

g_num = 0def test1():    global g_num    for i in range(10000):        mutex.acquire()        g_num += 1        mutex.release()    print("--- test1 g_num=%d ---" % g_num)def test2():    global g_num    for i in range(10000):        mutex.acquire()        g_num += 1        mutex.release()    print("--- test2 g_num=%d ---" % g_num)mutex = Lock()t1 = Thread(target=test1)t1.start()t2 = Thread(target=test2)t2.start()print("--- g_num=%d ---"%g_num)

  输出

---test1 g_num=10000------test2 g_num=20000---

 注意:第一次上锁程序不会锁住,第二次在没有解锁的情况下上锁程序才会锁住。

 

总结:

1、线程共享全局变量。

2、线程不共享函数里面的代码。

3、非全局变量不需要加锁 。

4、加锁的代码越少越好。

5、主线程等待子线程都执行完后才退出。

 

ThreadLocal对象

⼀个ThreadLocal变量虽然是全局变量,但每个线程都只能读写⾃⼰线程的独 ⽴副本,互不⼲扰。ThreadLocal解决了参数在⼀个线程中各个函数之间互相传递的问题。

import threadinglocal_school = threading.local()def process_student():    # 获取当前线程关联的student:    std = local_school.student    print("hello, %s (in %s)"%(std, threading.current_thread().name))def process_thread(name):    # 绑定ThreadLocal的student    local_school.student = name    process_student()t1 = threading.Thread(target=process_thread,args=("老李",), name="Thread-A")t2 = threading.Thread(target=process_thread,args=("老王",), name="Thread-B")t1.start()t2.start()#这里可以不加joint1.join()t2.join()

  输出

hello, 老李 (in Thread-A)hello, 老王 (in Thread-B)

 

ThreadLocal最常⽤的地⽅就是为每个线程绑定⼀个数据库连接,HTTP请求,⽤户身份信息等,这样⼀个线程的所有调⽤到的处理函数都可以⾮常⽅便地访问这些资源。

 

 异步

from multiprocessing import Poolimport timeimport osdef test():    print("---进程池中的进程--pid=%d,ppid=%d---"%(os.getpid(),os.getppid()))    for i in range(3):        print("---%d---"%i)        time.sleep(1)    return "hahah"def test2(args):    print("---callback func--pid=%d"%os.getpid())    print("---callback func--args=%s"%args)if __name__ == '__main__':    pool = Pool(3)    pool.apply_async(func=test,callback=test2)    while True:        time.sleep(1)        print("---主进程--pid=%d---"%os.getpid())

  输出

---进程池中的进程--pid=9228,ppid=3520------0------主进程--pid=3520------1------主进程--pid=3520------2------主进程--pid=3520------callback func--pid=3520    #pid为主进程id,也就是说主进程放下手中的工作,开始执行test2函数,这就是异步。---callback func--args=hahah---主进程--pid=3520------主进程--pid=3520------主进程--pid=3520--- ...

  

GIL也就是全局解释器锁,GIL保证一个进程里,同一时间只有一个线程在执行任务,只在cpython解释器里有GIL,jpython解释器就没有。

python里的多线程实际上是假多线程。

python里的多进程是真的多进程。

 

  

 

转载于:https://www.cnblogs.com/xone/p/10298337.html

你可能感兴趣的文章
常用界面布局
查看>>
C语言—— for 循环
查看>>
IBM lotus9.0测试版即将公测
查看>>
xml常用方法
查看>>
Cube Stacking(并差集深度+结点个数)
查看>>
AndroidStudio3更改包名失败
查看>>
jq 删除数组中的元素
查看>>
js URL中文传参乱码
查看>>
Leetcode 367. Valid Perfect Square
查看>>
UVALive 3635 Pie(二分法)
查看>>
win系统查看自己电脑IP
查看>>
Backup&recovery备份和还原 mysql
查看>>
一道面试题及扩展
查看>>
Unity 3D 我来了
查看>>
setup elk with docker-compose
查看>>
C++ GUI Qt4学习笔记03
查看>>
Java基础回顾 —反射机制
查看>>
c# 前台js 调用后台代码
查看>>
2017-02-20 可编辑div中如何在光标位置添加内容
查看>>
$.ajax()方法详解
查看>>