多线程-threading

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

from threading import Thread

import time

def test():
print("---1---")
time.sleep(1) for i in range(5):
t = Thread(target=test)
t.start()

  输出

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

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

使用thread子类创建线程

import threading
import time class 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 @ 0
I'm Thread-2 @ 1
I'm Thread-3 @ 2
I'm Thread-4 @ 3
I'm Thread-5 @ 4

  

线程的执行顺序

import threading
import time class 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 @ 0
I'm Thread-2 @ 0
I'm Thread-3 @ 0
I'm Thread-4 @ 0
I'm Thread-5 @ 0
I'm Thread-1 @ 1
I'm Thread-3 @ 1
I'm Thread-2 @ 1
I'm Thread-5 @ 1I'm Thread-4 @ 1 I'm Thread-1 @ 2
I'm Thread-2 @ 2
I'm Thread-3 @ 2
I'm Thread-5 @ 2I'm Thread-4 @ 2

  

线程共享全局变量

from threading import Thread
import time g_num = 100 def 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 = 0

def 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 threading

local_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()
#这里可以不加join
t1.join()
t2.join()

  输出

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

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

 异步

from multiprocessing import Pool
import time
import os def 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里的多进程是真的多进程。

  

多线程、互斥锁、异步、GIL的更多相关文章

  1. 6-[多线程]-互斥锁、GIL、死锁、递归锁、信号量

    1.互斥锁(排他锁) (1)不加锁的情况下 并发控制问题:多个事务并发执行,可能产生操作冲突,出现下面的3种情况 丢失修改错误 不能重复读错误 读脏数据错误 # mutex from threadin ...

  2. 并发编程 - 线程 - 1.互斥锁/2.GIL解释器锁/3.死锁与递归锁/4.信号量/5.Event事件/6.定时器

    1.互斥锁: 原理:将并行变成串行 精髓:局部串行,只针对共享数据修改 保护不同的数据就应该用不用的锁 from threading import Thread, Lock import time n ...

  3. Python Threading 线程/互斥锁/死锁/GIL锁

    导入线程包 import threading 准备函数线程,传参数 t1 = threading.Thread(target=func,args=(args,)) 类继承线程,创建线程对象 class ...

  4. C++ windows 多线程 互斥锁

    #include <opencv2/core/version.hpp> #include <opencv2/calib3d/calib3d.hpp> #include < ...

  5. java基础-多线程互斥锁

    多线程(JDK1.5的新特性互斥锁)* 1.同步 * 使用ReentrantLock类的lock()和unlock()方法进行同步* 2.通信 * 使用ReentrantLock类的newCondit ...

  6. python 并发编程 多线程 互斥锁

    互斥锁 并行变成串行,牺牲效率 保证数据安全,实现局部串行 保护不同的数据,应该加不同的锁 现在一个进程 可以有多个线程 所有线程都共享进程的地址空间 实现数据共享 共享带来问题就会出现竞争 竞争就会 ...

  7. Python多线程互斥锁

    import threading import time num=0 def Mylock(lock): global num lock.acquire() num=num+1 time.sleep( ...

  8. 笔记1 linux 多线程 互斥锁

    //mutex lock #include<stdio.h> #include<unistd.h> #include<pthread.h> struct test ...

  9. 并发编程~~~多线程~~~守护线程, 互斥锁, 死锁现象与递归锁, 信号量 (Semaphore), GIL全局解释器锁

    一 守护线程 from threading import Thread import time def foo(): print(123) time.sleep(1) print('end123') ...

  10. python 之 并发编程(守护线程与守护进程的区别、线程互斥锁、死锁现象与递归锁、信号量、GIL全局解释器锁)

    9.94 守护线程与守护进程的区别 1.对主进程来说,运行完毕指的是主进程代码运行完毕2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕​详细解释:1.主 ...

随机推荐

  1. 使用flask+SQL语句实现通过前台收到的信息向数据库中插入事件+初级CSS+HTML拯救一下我的主页·····

    1.使用flask+SQL语句实现**#@&&(懒得再扣一遍题目) 上代码: @app.route('/register', methods=['POST', 'GET']) def ...

  2. geoserver 安装部署发布

    转载:https://blog.csdn.net/u010763324/article/details/80719229 1. 从http://geoserver.org/下载GeoServer安装包 ...

  3. redis命令Map类型(五)

    如果存储一个对象 这个时候使用String 类型就不适合了,如果在String中修改一个数据的话,这就感到烦琐. hash 散列类型 ,他提供了字段与字段值的映射,当时字段值只能是字符串类型 命令: ...

  4. python基础分享

    # 一.变量命名规范 # 1.数字 字母 下划线 组成 # 2.不能数组开头和纯数字 # 3.不能用python相关关键字 # 4.不要用中文 # 5.要有意义 # 6.不要太长 # 7.区分大小写 ...

  5. Mybatis的分表实战

    前言: 以前写代码, 关于mysql的分库分表已被中间件服务所支持, 业务代码涉及的sql已规避了这块. 它对扩展友好, 你也不知道到底他分为多少库, 多少表, 一切都是透明的. 不过对于小的团队/工 ...

  6. Alienware R8外星人台式机安装双系统(WIN10+Ubuntu)的总结

    新电脑终于到了,然而外星人的系统比较特殊,很多东西和别的品牌(包括DELL)不一样, 同时NVIDIA显卡也带来了很多问题.重装了十几遍,查阅了上百篇文章后之后终于搞定了双系统. 其实核心问题很傻,就 ...

  7. 【EMV L2】2CS.001.00 ~ 2CS.007.00

    测试case要求,对于T=0和T=1卡,命令中是否存在Le是有差异的: - Select: Mandatory Command00 A4 04 00 Lc Command Data LeLc = 05 ...

  8. JavaSE-类

    一.基础概念:计算机语言的发展是接近人的思维方式演变:汇编语言(面向机器).C语言(面向过程).java(面向对象) 二.成员变量和局部变量: 1.全名定义一个类: Package 包名: Class ...

  9. Tajima's D

    Three ways to assess the nucleotide diversity (heterozygosity).The first is mean pairwise difference ...

  10. BZOJ-3105: 新Nim游戏 (nim博弈&线性基)

    pro: 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作,每次可以选一个火柴堆拿走若干根火柴.可以只拿一根,也可以拿走整堆火柴,但不能同时从 ...