锁
使用锁:
锁的语法
创建锁、锁定锁、释放锁
from
threading
import
Lock
#
创建锁
mutex =
Lock()
#
获取锁(上锁)
mutex.acquire()
#
释放锁(解锁)
mutex.release()
在锁定锁的过程中acquire()方法可以接受一个blocking参数,
如果设定blocking为True,则当前线程会堵塞,直到获取到这个锁为止(如果没有 指定,那么默认为True)
如果设定blocking为False,则当前线程不会堵塞
上锁和解锁的过程(假设是多线程调度):
这个锁一般是为共享资源服务的,即多个线程同时使用共享资源。这个锁同一时间只能有一个线程调度,其他线程阻塞,只有当前调度的线程释放这个锁,阻塞的线程才能调度。
锁的优点:
确保了某段关键代码只能有一个线程从头到尾完整的执行。
锁的缺点:
组织了多线程的并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大的降低了;代码中可能存在多个锁,如果多个线程拥有多个锁,容易造成死锁。
死锁的现象(实例):
#
死锁 两者都没有释放对方需要的锁,而释放的条件恰好是获取对方释放所需要的锁
#
线程1
class
MyThread1(threading.Thread):
def
__init__
(self):
super().
__init__
()
def
run(self):
#
线程1获取A锁
if
mutexA.acquire():
print
(self.name+
"
-----do1---up-----
"
)
sleep(
1
)
#
此时线程2获取了B锁,需要等待线程2释放B锁
if
mutexB.acquire():
print
(self.name +
"
-----do1---down-----
"
)
mutexB.release()
mutexA.release()
#
线程2
class
MyThread2(threading.Thread):
def
__init__
(self):
super().
__init__
()
def
run(self):
#
线程2获取B锁
if
mutexB.acquire():
print
(self.name +
"
-----do2---up-----
"
)
sleep(
1
)
#
此时线程1获取了A锁,需要等待线程1释放A锁
if
mutexA.acquire():
print
(self.name +
"
-----do2---down-----
"
)
mutexA.release()
mutexB.release()
mutexA
=
threading.Lock()
mutexB
=
threading.Lock()
if
__name__
==
'
__main__
'
:
#
线程1和线程2同时执行
t1 =
MyThread1()
t2
=
MyThread2()
t1.start()
t2.start()
避免死锁的方法:银行家算法
多进程与多线程比较及选择
是否采用多任务处理,取决于我们的任务类型
如果是计算密集型,需要大量的CPU资源进行运算,代码的运行效率至关重 要,这样的任务一般不使用多线程进行,因为频繁的任务调度会拖慢CPU的
运算。
如果是IO密集型,涉及到硬盘读写,网络读写等的任务,更多的时间在等待 IO操作完成,这一类任务可以放到多线程或多进程中来进行。
单线程、多线程、多进程(一起实现同一代码的时间)
#
单线程、多线程、多进程的使用及不同
#
简单的求和
def
fib(x):
res
=
0
for
i
in
range(100000000
):
res
+= i*
x
return
res
#
阶乘
def
fac(x):
if
x < 2
:
return
1
return
x*fac(x-1
)
#
简单的求和
def
sum(x):
res
=
0
for
i
in
range(50000000
):
res
+= i*
x
return
res
#
函数列表
funcs =
[fib, fac, sum]
n
= 100
class
MyThread(threading.Thread):
def
__init__
(self, func, args, name=
""
):
super().
__init__
()
self.name
=
name
self.func
=
func
self.args
=
args
self.res
=
0
def
getResult(self):
return
self.res
def
run(self):
print
(
"
starting
"
, self.name,
"
at:
"
, ctime())
self.res
=
self.func(self.args)
print
(self.name,
"
finished at:
"
, ctime())
def
main():
nfuncs
=
range(len(funcs))
print
(
"
单线程
"
.center(30,
"
*
"
))
start
=
time()
for
i
in
nfuncs:
print
(
"
start {} at: {}
"
.format(funcs[i].
__name__
, ctime()))
start_task
=
time()
print
(funcs[i](n))
end_task
=
time()
print
(
"
任务 耗时:
"
, end_task-
start_task)
print
(
"
{} finished at: {}
"
.format(funcs[i].
__name__
, ctime()))
end
=
time()
print
(
"
单线程运行时间:
"
, end-
start)
print
(
"
单线程结束:
"
.center(30,
"
*
"
))
print
()
print
(
"
多线程
"
.center(30,
"
*
"
))
start
=
time()
threads
=
[]
for
i
in
nfuncs:
#
一个线程绑定一个函数
t = MyThread(funcs[i], n, funcs[i].
__name__
)
threads.append(t)
for
i
in
nfuncs:
#
同时启动线程
threads[i].start()
for
i
in
nfuncs:
threads[i].join()
print
(threads[i].getResult())
end
=
time()
print
(
"
多线程运行时间:
"
, end-
start)
print
(
"
多线程结束:
"
.center(30,
"
*
"
))
print
()
print
(
"
多进程
"
.center(30,
"
*
"
))
start
=
time()
process_list
=
[]
for
i
in
nfuncs:
#
一个进程绑定一个函数
t = Process(target=funcs[i], args=
(n, ))
process_list.append(t)
for
i
in
nfuncs:
#
同时启动进程
process_list[i].start()
for
i
in
nfuncs:
process_list[i].join()
end
=
time()
print
(
"
多进程运行时间:
"
, end -
start)
print
(
"
多进程结束:
"
.center(30,
"
*
"
))
if
__name__
==
"
__main__
"
:
main()

