Python 线程锁

一、线程锁(互斥锁Mutex)

  1、一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,此时,如果2个线程同时要修改同一份数据,会出现什么状况?

#!/usr/bin/python
# -*- coding : utf-8 -*-
# 作者: Presley
# 时间: 2018-11-20
# 邮箱:1209989516@qq.com
# 这是我用来练习python线程锁的测试脚本

import threading
import time


def addNum():
    global num #在每个线程中都获取这个全局变量
    print("--get num:",num)
    time.sleep(1)
    num -= 1 #对此公共变量进行-1操作
num = 100 #设定一个共享变量
thread_list = []
for i in range(100):
    t = threading.Thread(target=addNum)
    t.start()
    thread_list.append(t)
for t in thread_list: #等待所有线程执行完毕
    t.join()
print("final num:",num)

 结果:python2中每次结果都会不一样,python3中结果都是0

...
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
final num: 0

  2、加锁后

#!/usr/bin/python
# -*- coding : utf-8 -*-
# 作者: Presley
# 时间: 2018-11-20
# 邮箱:1209989516@qq.com
# 这是我用来练习python线程锁的测试脚本

import threading
import time


def addNum():
    global num #在每个线程中都获取这个全局变量
    print("--get num:",num)
    time.sleep(1)
    lock.acquire() #获取一把锁 #加锁后相当于变成串行的了
    num -= 1 #对此公共变量进行-1操作
    lock.release() #必须释放,不施放所有的都等待了

lock = threading.Lock() #定义一个锁实例
num = 100 #设定一个共享变量
thread_list = []
for i in range(100):
    t = threading.Thread(target=addNum)
    t.start()
    thread_list.append(t)
for t in thread_list: #等待所有线程执行完毕
    t.join()
print("final num:",num)

结果:

...
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
--get num: 100
final num: 0

 二、递归锁(RLock)

  1、说白了就是在一把大锁中还要再包含子锁。

    

#!/usr/bin/python
# -*- coding : utf-8 -*-
# 作者: Presley
# 时间: 2018-11-21
# 邮箱:1209989516@qq.com
# 这是我用来练习python线程锁的测试脚本

import threading
import time


def run1():
    print("grab the first part data")
    lock.acquire()
    global num
    num += 1
    lock.release()
    return num
def run2():
    print("grab the second part data")
    lock.acquire()
    global num2
    num2 += 1
    lock.release()
    return num2
def run3():
    lock.acquire() #之所以在执行run1和run2之间加一把锁是因为确保两个方法一块运行完毕
    res = run1()
    print("-------between run1 and run2-----------")
    res2 = run2()
    lock.release()
    print(res,res2)
if __name__ == "__main__":
    num,num2 = 0,0
    lock = threading.RLock()
    for i in range(10):
        t = threading.Thread(target=run3)
        t.start()
while threading.active_count() != 1:    #现在还有几个线程,如果等于1表示只有主线程了,否则表示还没有执行完
    print(threading.active_count())
else:
    print("--all threads done--")
    print(num,num2)

执行结果:

grab the first part data
-------between run1 and run2-----------
grab the second part data
1 1
grab the first part data
-------between run1 and run2-----------
grab the second part data
2 2
grab the first part data
-------between run1 and run2-----------
grab the second part data
3 3
grab the first part data
-------between run1 and run2-----------
grab the second part data
4 4
grab the first part data
-------between run1 and run2-----------
grab the second part data
5 5
grab the first part data
-------between run1 and run2-----------
grab the second part data
6 6
grab the first part data
-------between run1 and run2-----------
grab the second part data
7 7
grab the first part data
-------between run1 and run2-----------
grab the second part data
8 8
grab the first part data
-------between run1 and run2-----------
grab the second part data
9 9
grab the first part data
-------between run1 and run2-----------
grab the second part data
10 10
--all threads done--
10 10

三、信号量(Semaphore)

  1、互斥锁,同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据,比如厕所有三个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。

#!/usr/bin/python
# -*- coding : utf-8 -*-
# 作者: Presley
# 时间: 2018-11-21
# 邮箱:1209989516@qq.com
# 这是我用来练习python线程锁的测试脚本

import threading
import time


def run(n):
    semaphore.acquire()
    time.sleep(1)
    print("run the thread:%s \n" %n)
    semaphore.release()

if __name__ == "__main__":
    num = 0
    semaphore = threading.BoundedSemaphore(3) #最多允许5个线程同时运行,类似于线程池的概念
    for i in range(20):
        t = threading.Thread(target=run,args=(i,))
        t.start()

  执行结果:

run the thread:1 

run the thread:0 

run the thread:2 

run the thread:3 

run the thread:4 

run the thread:5 

run the thread:6 

run the thread:7 
run the thread:8 


run the thread:9 

run the thread:11 
run the thread:10 


run the thread:12 

run the thread:13 
run the thread:14 


run the thread:15 

run the thread:17 

run the thread:16 

run the thread:18 

run the thread:19 

 

posted @ 2018-11-20 20:20  Presley  阅读(346)  评论(0编辑  收藏  举报