多线程、互斥锁、异步、GIL
多线程-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的更多相关文章
- 6-[多线程]-互斥锁、GIL、死锁、递归锁、信号量
1.互斥锁(排他锁) (1)不加锁的情况下 并发控制问题:多个事务并发执行,可能产生操作冲突,出现下面的3种情况 丢失修改错误 不能重复读错误 读脏数据错误 # mutex from threadin ...
- 并发编程 - 线程 - 1.互斥锁/2.GIL解释器锁/3.死锁与递归锁/4.信号量/5.Event事件/6.定时器
1.互斥锁: 原理:将并行变成串行 精髓:局部串行,只针对共享数据修改 保护不同的数据就应该用不用的锁 from threading import Thread, Lock import time n ...
- Python Threading 线程/互斥锁/死锁/GIL锁
导入线程包 import threading 准备函数线程,传参数 t1 = threading.Thread(target=func,args=(args,)) 类继承线程,创建线程对象 class ...
- C++ windows 多线程 互斥锁
#include <opencv2/core/version.hpp> #include <opencv2/calib3d/calib3d.hpp> #include < ...
- java基础-多线程互斥锁
多线程(JDK1.5的新特性互斥锁)* 1.同步 * 使用ReentrantLock类的lock()和unlock()方法进行同步* 2.通信 * 使用ReentrantLock类的newCondit ...
- python 并发编程 多线程 互斥锁
互斥锁 并行变成串行,牺牲效率 保证数据安全,实现局部串行 保护不同的数据,应该加不同的锁 现在一个进程 可以有多个线程 所有线程都共享进程的地址空间 实现数据共享 共享带来问题就会出现竞争 竞争就会 ...
- Python多线程互斥锁
import threading import time num=0 def Mylock(lock): global num lock.acquire() num=num+1 time.sleep( ...
- 笔记1 linux 多线程 互斥锁
//mutex lock #include<stdio.h> #include<unistd.h> #include<pthread.h> struct test ...
- 并发编程~~~多线程~~~守护线程, 互斥锁, 死锁现象与递归锁, 信号量 (Semaphore), GIL全局解释器锁
一 守护线程 from threading import Thread import time def foo(): print(123) time.sleep(1) print('end123') ...
- python 之 并发编程(守护线程与守护进程的区别、线程互斥锁、死锁现象与递归锁、信号量、GIL全局解释器锁)
9.94 守护线程与守护进程的区别 1.对主进程来说,运行完毕指的是主进程代码运行完毕2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕详细解释:1.主 ...
随机推荐
- Spring Boot 异步运用
使用@Async标签 导入包 org.springframework.scheduling.annotation.Async 并配置并发线程池asyncTaskConfig 实现AsyncConfig ...
- tp5 删除服务器文件
public function test(){ //ROOT_PATH . 'public' . DS . 'uploads' $filename = ROOT_PATH . 'public' . D ...
- python学习第二次笔记
python学习第二次记录 1.格式化输出 name = input('请输入姓名') age = input('请输入年龄') height = input('请输入身高') msg = " ...
- 周强、张季跃,马凯军《面向对象与程序设计Java》第十四周学习总结
实验十四 Swing图形界面组件 实验时间 20178-11-29 理论部分:不使用布局管理器 有时候可能不想使用任何布局管理器,而只 是想把组件放在一个固定的位置上.下面是将一 个组件定位到某个绝 ...
- 【算法导论】【排序】—— 计数排序(counting sort)
计数排序的特点: 需要额外的数组以存储: 中间过程数据(记为数组 C),数组 C 的下标是待排序序列的元素值,下标对应的值为出现的次数: 排序后的序列(记为 B),计数排序仅获取原始待排序序列的值,对 ...
- jQuery-4.动画篇---自定义动画
jQuery中动画animate(上) 有些复杂的动画通过之前学到的几个动画函数是不能够实现,这时候就需要强大的animate方法了 操作一个元素执行3秒的淡入动画,对比一下2组动画设置的区别 $(e ...
- VirtualBox 使用物理硬盘
/******************************************************************************* * VirtualBox 使用物理硬盘 ...
- 基本的java加密算法MD5等等
简单的java加密算法有: BASE64 严格地说,属于编码格式,而非加密算法 MD5 (Message Digest algorithm 5,信息摘要算法) SH ...
- Qt实现 动态化遍历二叉树(前中后层次遍历)
binarytree.h 头文件 #ifndef LINKEDBINARYTREE_H #define LINKEDBINARYTREE_H #include<c++/algorithm> ...
- Springboot 部署到linux(二)
之前写了一篇部署的文章,但是打包时会运行所有的单元测试,如果不想测试的话,可以采用这种方式. 第一部分:打包 1.pom.xm添加配置 <plugin> <groupId>or ...