python多线程————4、线程同步之Lock,RLock

     在多线程同时请求同一个资源并进行修改时可能会造成结果出错,例如共享变量

     

from dis import dis
import threading
a = 0
def add():
    global a
    a += 1

def desc():
    global a
    a -= 1

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

thread_add = threading.Thread(target=add)
thread_desc = threading.Thread(target=desc)
thread_add.start()
thread_desc.start()
thread_add.join()
thread_desc.join()
print(a)

 在上面的代码中存在一个什么问题呢?虽然运行没能看出什么问题,看dis这个模块打印出的内容,一个+=运算是先load a 然后load 1 然后做运算再把结果赋值给a。那问题来了如果a同时被desc和add 加载呢,那desc和add加载进去的a值都为0,那a做add和desc运算后结果可能为1 或者-1而不是0。

              0 LOAD_GLOBAL              0 (a)
              2 LOAD_CONST               1 (1)
              4 INPLACE_ADD
              6 STORE_GLOBAL             0 (a)
              8 LOAD_CONST               0 (None)

要怎么解决这个同步问题呢,解决方法是给资源加把锁Lock,RLock(可重如的锁)

from threading import Lock
total = 0
lock = Lock()
def add():
    global total
    global lock
    #1.do something1
    #2. io操作
    #3.do someting3
    for i in range(1000000):
        lock.acquire()
        total += 1
        lock.release()
def desc():
    global total
    global lock
    for i in range(1000000):
        lock.acquire()
        total -= 1
        lock.release()
import threading
thread1 = threading.Thread(target=add)
thread2 = threading.Thread(target=desc)
thread1.start()
thread2.start()

thread1.join()
thread2.join()
print(total)
print(dis(add))

 Lock在使用过程中不可以重入,重入会造成死锁,比如

lock.acquire()
lock.acquire()

而CLock是在同一线程中是可以重入的,但要记得释放相同数量的锁。

猜你喜欢

转载自blog.csdn.net/sinat_34461756/article/details/83781300