04、线程同步[ 线程安全 ] -- Lock 和 RLock锁

01、线程不安全举例

import threading

total = 0


def add():
    global total
    for i in range(1000000):
        total = total + 1


def desc():
    global total
    for i in range(1000000):
        total = total - 1


thread_01 = threading.Thread(target=add)
thread_02 = threading.Thread(target=desc)

thread_01.start()
thread_02.start()

thread_01.join()
thread_02.join()

print(total)

******  执行结果  ******
可能为 0~2000000 之间任意一个值,例如1356812

02、通过字节码分析一下为什么线程数据不同步

import dis


def add(a):
    a += 1

def desc(a):
    a -= 1

print(dis.dis(add))
print(dis.dis(desc))

**************  字节码结果如下  **************
  5           0 LOAD_FAST                0 (a)  --  加载变量 a = 0
              2 LOAD_CONST               1 (1)  --  加载常量 1
              4 INPLACE_ADD                     --  执行 + 操作 a = a+1
              6 STORE_FAST               0 (a)  --  存储数据给a a = 1
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE
None
  8           0 LOAD_FAST                0 (a)  --  加载变量 a = 0
              2 LOAD_CONST               1 (1)  --  加载常量 1
              4 INPLACE_SUBTRACT                --  执行 - 操作 a = a-1
              6 STORE_FAST               0 (a)  --  存储数据给a a= -1
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE
None

03、python提供了几种线程同步机制 【也就是几种锁机制】

--加锁:让一个时间段只有一个代码段||对象在运行或被操作
    --导入模块:from threading import Lock
    --锁的声明:lock = Lock()
    --获得锁:lock.acquire()
    --释放锁:lock.release()

--锁的使用缺点:
    --性能降低
    -死锁:
        --常见的四个条件:
            --
            --
            --
            --
        --常见死锁代码示例:
          --01、执行的需要的资源相互依存
            A 锁 锁住C资源,同时需要D资源
            B 锁 锁住D资源,同时需要C资源
            两个锁的执行都依赖于对方的执行结束
          --02、同一把锁嵌套

--针对上面同一把锁嵌套问题,我们可以使用嵌套锁进行解决
    --RLock:可重入的锁,方法和Lock基本一致
        
--加锁的代码示例:这里不再使用global,而是传参的方式。因为python中传递的就是参数的引用
--记住锁的使用会导致性能降低
import threading
from threading import Lock


def add(total, lock):
    for i in range(1000000):
        lock.acquire()
        total = total + 1
        lock.release()


def desc(total, lock):
    for i in range(1000000):
        lock.acquire()
        total = total - 1
        lock.release()

total = 0
lock = Lock()

thread_01 = threading.Thread(target=add, args=(total, lock))
thread_02 = threading.Thread(target=desc, args=(total, lock))

thread_01.start()
thread_02.start()

thread_01.join()
thread_02.join()

print(total)
--RLock:可重入的锁的代码示例:
import threading
from threading import Lock, RLock


def add(total, lock):
    for i in range(1000000):
        lock.acquire()
        lock.acquire()
        total = total + 1
        lock.release()
        lock.release()


def desc(total, lock):
    for i in range(1000000):
        lock.acquire()
        lock.acquire()
        total = total - 1
        lock.release()
        lock.release()

total = 0
lock = RLock()

thread_01 = threading.Thread(target=add, args=(total, lock))
thread_02 = threading.Thread(target=desc, args=(total, lock))

thread_01.start()
thread_02.start()

thread_01.join()
thread_02.join()

print(total)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值