ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python-线程同步 - Lock、RLock学习

2021-02-27 11:05:26  阅读:261  来源: 互联网

标签:zabbixweb python Lock zabbixapiweb RLock project data


 dis库是python(默认的CPython)自带的一个库,可以用来分析字节码

import dis


def add1():
    a += 1


def desc1():
    b -= 1
    print(b)

print(dis.dis(add1))
print(dis.dis(desc1))

 执行结果:

前面的数字 17、21、22 第一列表示对应源代码的行数。第二列的数字是字节码的索引。第三列是指令本身对应的人类可读的名字。第四列表示指令的参数。第5列则是计算后的实际参数。

 17           0 LOAD_FAST                0 (a)  #加载变量a到内存   
              2 LOAD_CONST               1 (1)  #加载1 到内存
              4 INPLACE_ADD  #执行加 计算
              6 STORE_FAST               0 (a)  #把结果赋值给a
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE
None
 21           0 LOAD_FAST                0 (b)
              2 LOAD_CONST               1 (1)
              4 INPLACE_SUBTRACT
              6 STORE_FAST               0 (b)

 22           8 LOAD_GLOBAL              0 (print)
             10 LOAD_FAST                0 (b)
             12 CALL_FUNCTION            1
             14 POP_TOP
             16 LOAD_CONST               0 (None)
             18 RETURN_VALUE
None

 

假如add1和desc1函数里的 变量 a和b使用同一个全局变量,并分别放到多线程中运行,:

import dis
from threading import Thread
from threading import Lock
a = 0
lock = Lock()
def add1():
    global a
    global lock

    for x in range(1000000):
        # lock.acquire()
        a += 1
        # lock.release()
def desc1():
    global a
    global lock

    for x in range(1000000):
        # lock.acquire()
        a -= 1
        # lock.release()
if __name__ == "__main__":
    thread1 = Thread(target=add1)
    thread2 = Thread(target=desc1)
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()
    print(a)

执行结果会变,因为Thread的run方法不是线程安全的,GIL 在线程运行过程中,会不断切换,又共用的同个变量就出现这问题了。

(zabbixweb) D:\data\python\zabbixapiweb\project\project>d:/data/python/environment/zabbixweb/Scripts/python.exe d:/data/python/zabbixapiweb/project/project/test16.py     
-124668

(zabbixweb) D:\data\python\zabbixapiweb\project\project>d:/data/python/environment/zabbixweb/Scripts/python.exe d:/data/python/zabbixapiweb/project/project/test16.py     
694972

(zabbixweb) D:\data\python\zabbixapiweb\project\project>d:/data/python/environment/zabbixweb/Scripts/python.exe d:/data/python/zabbixapiweb/project/project/test16.py     
-246256

(zabbixweb) D:\data\python\zabbixapiweb\project\project>d:/data/python/environment/zabbixweb/Scripts/python.exe d:/data/python/zabbixapiweb/project/project/test16.py     
-310544

(zabbixweb) D:\data\python\zabbixapiweb\project\project>d:/data/python/environment/zabbixweb/Scripts/python.exe d:/data/python/zabbixapiweb/project/project/test16.py     
-592669

(zabbixweb) D:\data\python\zabbixapiweb\project\project>

为了解决这个问题,Python 的 threading 模块引入了锁(Lock)。threading 模块提供了 Lock 和 RLock 两个类,它们都提供了如下两个方法来加锁和释放锁:

  1. acquire(blocking=True, timeout=-1):请求对 Lock 或 RLock 加锁,其中 timeout 参数指定加锁多少秒。
  2. release():释放锁。


Lock 和 RLock 的区别如下:

  • threading.Lock:它是一个基本的锁对象,每次只能锁定一次,其余的锁请求,需等待锁释放后才能获取。
  • threading.RLock:它代表可重入锁(Reentrant Lock)。对于可重入锁,在同一个线程中可以对它进行多次锁定,也可以多次释放。如果使用 RLock,那么 acquire() 和 release() 方法必须成对出现。如果调用了 n 次 acquire() 加锁,则必须调用 n 次 release() 才能释放锁。


由此可见,RLock 锁具有可重入性。也就是说,同一个线程可以对已被加锁的 RLock 锁再次加锁,RLock 对象会维持一个计数器来追踪 acquire() 方法的嵌套调用,线程在每次调用 acquire() 加锁后,都必须显式调用 release() 方法来释放锁。所以,一段被锁保护的方法可以调用另一个被相同锁保护的方法。

Lock 是控制多个线程对共享资源进行访问的工具。通常,锁提供了对共享资源的独占访问,每次只能有一个线程对 Lock 对象加锁,线程在开始访问共享资源之前应先请求获得 Lock 对象。当对共享资源访问完成后,程序释放对 Lock 对象的锁定。

import dis
from threading import Thread
from threading import Lock
a = 0
lock = Lock()
def add1():
    global a
    global lock

    for x in range(1000000):
        lock.acquire()
        a += 1
        lock.release()
def desc1():
    global a
    global lock

    for x in range(1000000):
        lock.acquire()
        a -= 1
        lock.release()
if __name__ == "__main__":
    thread1 = Thread(target=add1)
    thread2 = Thread(target=desc1)
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()
    print(a)
(zabbixweb) D:\data\python\zabbixapiweb\project\project>d:/data/python/environment/zabbixweb/Scripts/python.exe d:/data/python/zabbixapiweb/project/project/test16.py     
0

(zabbixweb) D:\data\python\zabbixapiweb\project\project>d:/data/python/environment/zabbixweb/Scripts/python.exe d:/data/python/zabbixapiweb/project/project/test16.py     
0

 

标签:zabbixweb,python,Lock,zabbixapiweb,RLock,project,data
来源: https://www.cnblogs.com/laonicc/p/14453639.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有