- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章详解python多线程、锁、event事件机制的简单使用由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
线程和进程 。
1、线程共享创建它的进程的地址空间,进程有自己的地址空间 。
2、线程可以访问进程所有的数据,线程可以相互访问 。
3、线程之间的数据是独立的 。
4、子进程复制线程的数据 。
5、子进程启动后是独立的 ,父进程只能杀掉子进程,而不能进行数据交换 。
6、修改线程中的数据,都是会影响其他的线程,而对于进程的更改,不会影响子进程 。
threading.Thread 。
Thread 是threading模块中最重要的类之一,可以使用它来创建线程。有两种方式来创建线程:一种是通过继承Thread类,重写它的run方法;另一种是创建一个threading.Thread对象,在它的初始化函数(__init__)中将可调用对象作为参数传入。 先来看看通过继承threading.Thread类来创建线程的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import
threading
import
time
class
MyThread(threading.Thread):
def
__init__(
self
, arg):
# super(MyThread, self).__init__() # 新式类继承原有方法写法
threading.Thread.__init__(
self
)
self
.arg
=
arg
def
run(
self
):
time.sleep(
2
)
print
(
self
.arg)
for
i
in
range
(
10
):
thread
=
MyThread(i)
print
(thread.name)
thread.start()
|
另外一种创建线程的方法:
1
2
3
4
5
6
7
8
9
10
11
|
import
threading
import
time
def
process(arg):
time.sleep(
2
)
print
(arg)
for
i
in
range
(
10
):
t
=
threading.Thread(target
=
process, args
=
(i,))
print
(t.name)
t.start()
|
Thread类还定义了以下常用方法与属性:
Thread.getName() 获取线程名称 。
Thread.setName() 设置线程名称 。
Thread.name 线程名称 。
Thread.ident 获取线程的标识符。线程标识符是一个非零整数,只有在调用了start()方法之后该属性才有效,否则它只返回None 。
判断线程是否是激活的(alive)。从调用start()方法启动线程,到run()方法执行完毕或遇到未处理异常而中断 这段时间内,线程是激活的 。
Thread.is_alive() Thread.isAlive() 。
Thread.join([timeout]) 调用Thread.join将会使主调线程堵塞,直到被调用线程运行结束或超时。参数timeout是一个数值类型,表示超时时间,如果未提供该参数,那么主调线程将一直堵塞到被调线程结束 。
Python GIL(Global Interpreter Lock) 。
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.
线程锁的使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# 锁:GIL 全局解释器 它是为了保证线程在运行过程中不被抢占
number
=
0
lock
=
threading.RLock()
# 创建锁
def
run(num):
lock.acquire()
# 加锁
global
number
number
+
=
1
print
(number)
time.sleep(
2
)
lock.release()
# 释放锁
for
i
in
range
(
10
):
t
=
threading.Thread(target
=
run, args
=
(i, ))
t.start()
|
Join & Daemon 。
主线程A中,创建了子线程B,并且在主线程A中调用了B.setDaemon(),这个的意思是,把主线程A设置为守护线程,这时候,要是主线程A执行结束了,就不管子线程B是否完成,一并和主线程A退出.这就是setDaemon方法的含义,这基本和join是相反的。此外,还有个要特别注意的:必须在start() 方法调用之前设置,如果不设置为守护线程,程序会被无限挂起.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class
MyThread1(threading.Thread):
def
__init__(
self
):
threading.Thread.__init__(
self
)
def
run(
self
):
print
(
"thread start"
)
time.sleep(
3
)
print
(
'thread end'
)
print
(
'main start'
)
thread1
=
MyThread1()
# thread1.setDaemon(True) # 设置子线程是否跟随主线程一起结束
thread1.start()
time.sleep(
1
)
print
(
'satrt join'
)
# thread1.join() # 使主线程阻塞,直至子线程运行完毕再继续主线程
print
(
'end join'
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
def
run(n):
print
(
'[%s]------running----\n'
%
n)
time.sleep(
2
)
print
(
'--done--'
)
def
main():
for
i
in
range
(
5
):
t
=
threading.Thread(target
=
run, args
=
[i,])
t.start()
# t.join()
print
(
'starting thread'
, t.getName())
m
=
threading.Thread(target
=
main,args
=
[])
# m.setDaemon(True) # 将主线程设置为Daemon线程,它退出时,其它子线程会同时退出,不管是否执行完任务
m.start()
# m.join() # 使主线程阻塞,直至子线程运行完毕再继续主线程
print
(
"---main thread done----"
)
|
线程锁(互斥锁Mutex) 。
一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,此时,如果2个线程同时要修改同一份数据,会出现什么状况?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
num
=
100
# 设定一个共享变量
def
subNum():
global
num
# 在每个线程中都获取这个全局变量
print
(
'--get num:'
, num)
time.sleep(
2
)
num
-
=
1
# 对此公共变量进行-1操作
thread_list
=
[]
for
i
in
range
(
100
):
t
=
threading.Thread(target
=
subNum)
t.start()
thread_list.append(t)
for
t
in
thread_list:
# 等待所有线程执行完毕
t.join()
print
(
'final num:'
, num)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# 加锁版本
def
subNum():
global
num
# 在每个线程中都获取这个全局变量
print
(
'--get num:'
, num)
time.sleep(
1
)
lock.acquire()
# 修改数据前加锁
num
-
=
1
# 对此公共变量进行-1操作
lock.release()
# 修改后释放
num
=
100
# 设定一个共享变量
thread_list
=
[]
lock
=
threading.Lock()
# 生成全局锁
for
i
in
range
(
100
):
t
=
threading.Thread(target
=
subNum)
t.start()
thread_list.append(t)
for
t
in
thread_list:
# 等待所有线程执行完毕
t.join()
print
(
'final num:'
, num)
|
Rlock与Lock的区别:
RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。否则会出现死循环,程序不知道解哪一把锁。注意:如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的锁 。
Events 。
Python提供了Event对象用于线程间通信,它是由线程设置的信号标志,如果信号标志位真,则其他线程等待直到信号接触。 Event对象实现了简单的线程通信机制,它提供了设置信号,清除信号,等待等用于实现线程间的通信.
event = threading.Event() 创建一个event 。
1 设置信号 event.set() 。
使用Event的set()方法可以设置Event对象内部的信号标志为真。Event对象提供了isSet()方法来判断其内部信号标志的状态。 当使用event对象的set()方法后,isSet()方法返回真 。
2 清除信号 event.clear() 。
使用Event对象的clear()方法可以清除Event对象内部的信号标志,即将其设为假,当使用Event的clear方法后,isSet()方法返回假 。
3 等待 event.wait() 。
Event对象wait的方法只有在内部信号为真的时候才会很快的执行并完成返回。当Event对象的内部信号标志位假时, 则wait方法一直等待到其为真时才返回。也就是说必须set新号标志位真 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
def
do(event):
print
(
'start'
)
event.wait()
print
(
'execute'
)
event_obj
=
threading.Event()
for
i
in
range
(
10
):
t
=
threading.Thread(target
=
do, args
=
(event_obj,))
t.start()
event_obj.clear()
inp
=
input
(
'输入内容:'
)
if
inp
=
=
'true'
:
event_obj.
set
()
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:https://segmentfault.com/a/1190000014619654 。
最后此篇关于详解python多线程、锁、event事件机制的简单使用的文章就讲到这里了,如果你想了解更多关于详解python多线程、锁、event事件机制的简单使用的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在努力实现以下目标, 假设我有字符串: ( z ) ( A ( z ) ( A ( z ) ( A ( z ) ( A ( z ) ( A ) ) ) ) ) 我想编写一个正则
给定: 1 2 3 4 5 6
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
大家好,我卡颂。 Svelte问世很久了,一直想写一篇好懂的原理分析文章,拖了这么久终于写了。 本文会围绕一张流程图和两个Demo讲解,正确的食用方式是用电脑打开本文,跟着流程图、Demo一
身份证为15位或者18位,15位的全为数字,18位的前17位为数字,最后一位为数字或者大写字母”X“。 与之匹配的正则表达式: ?
我们先来最简单的,网页的登录窗口; 不过开始之前,大家先下载jquery的插件 本人习惯用了vs2008来做网页了,先添加一个空白页 这是最简单的的做法。。。先在body里面插入 <
1、MySQL自带的压力测试工具 Mysqlslap mysqlslap是mysql自带的基准测试工具,该工具查询数据,语法简单,灵活容易使用.该工具可以模拟多个客户端同时并发的向服务器发出
前言 今天大姚给大家分享一款.NET开源(MIT License)、免费、简单、实用的数据库文档(字典)生成工具,该工具支持CHM、Word、Excel、PDF、Html、XML、Markdown等
Go语言语法类似于C语言,因此熟悉C语言及其派生语言( C++、 C#、Objective-C 等)的人都会迅速熟悉这门语言。 C语言的有些语法会让代码可读性降低甚至发生歧义。Go语言在C语言的
我正在使用快速将 mkv 转换为 mp4 ffmpeg 命令 ffmpeg -i test.mkv -vcodec copy -acodec copy new.mp4 但不适用于任何 mkv 文件,当
我想计算我的工作簿中的工作表数量,然后从总数中减去特定的工作表。我错过了什么?这给了我一个对象错误: wsCount = ThisWorkbook.Sheets.Count - ThisWorkboo
我有一个 perl 文件,用于查看文件夹中是否存在 ini。如果是,它会从中读取,如果不是,它会根据我为它制作的模板创建一个。 我在 ini 部分使用 Config::Simple。 我的问题是,如果
尝试让一个 ViewController 通过标准 Cocoa 通知与另一个 ViewController 进行通信。 编写了一个简单的测试用例。在我最初的 VC 中,我将以下内容添加到 viewDi
我正在绘制高程剖面图,显示沿路径的高程增益/损失,类似于下面的: Sample Elevation Profile with hand-placed labels http://img38.image
嗨,所以我需要做的是最终让 regStart 和 regPage 根据点击事件交替可见性,我不太担心编写 JavaScript 函数,但我根本无法让我的 regPage 首先隐藏。这是我的代码。请简单
我有一个非常简单的程序来测量一个函数花费了多少时间。 #include #include #include struct Foo { void addSample(uint64_t s)
我需要为 JavaScript 制作简单的 C# BitConverter。我做了一个简单的BitConverter class BitConverter{ constructor(){} GetBy
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
我是 Simple.Data 的新手。但我很难找到如何进行“分组依据”。 我想要的是非常基本的。 表格看起来像: +________+ | cards | +________+ | id |
我现在正在开发一个 JS UDF,它看起来遵循编码。 通常情况下,由于循环计数为 2,Alert Msg 会出现两次。我想要的是即使循环计数为 3,Alert Msg 也只会出现一次。任何想法都
我是一名优秀的程序员,十分优秀!