Lock(线程锁)(互斥锁)

锁

from threading import Thread
x=0
def foo():
    global  x
    for i in range(10000000):
        if i%1000 ==0:
            print(x)
        x+=1

t_l = []
for i in range(2):
    t = Thread(target=foo)
    t.start()
    t_l.append(t)
for i in t_l:
    i.join()

print(x)

对可能发生数据安全的地方进行上锁

上锁外的地方还是并发的,

但上锁的代码就变成了串行

保证了数据安全

死锁

from threading import Thread,Lock, current_thread
import time
lo = Lock()
lc = Lock()


def func1():
    lo.acquire()
    print(current_thread().name, "抢到了锁1")

    lc.acquire()
    print(current_thread().name, "抢到了锁2")
    lc.release()
    print(current_thread().name, "释放了锁2")
    lo.release()
    print(current_thread().name, "释放了锁1")


def func2():
    lc.acquire()
    print(current_thread().name, "抢到了锁2")
    time.sleep(0.1)
    lo.acquire()
    print(current_thread().name, "抢到了锁1")
    lo.release()
    print(current_thread().name, "释放了锁1")
    lc.release()
    print(current_thread().name, "释放了锁2")


def run():
    func1()
    func2()


for i in range(10):
    t = Thread(target=run)
    t.start()

指两个或两个以上的线程在执行过程中

由于竞争资源或者由于彼此通信而造成的一种阻塞的现象

若无外力作用,它们都将无法继续执行下去

即:线程手里互相有其它线程要执行下去的必备资源

RLock(递归锁)

import time
from threading import Thread, RLock, current_thread

rl = RLock()


def func1():
    rl.acquire()
    print(current_thread().name, "抢到了锁+1")

    rl.acquire()
    print(current_thread().name, "抢到了锁+1")
    rl.release()
    print(current_thread().name, "释放了锁-1")
    rl.release()
    print(current_thread().name, "释放了锁-2")


def func2():
    rl.acquire()
    print(current_thread().name, "抢到了锁+1")
    time.sleep(0.1)
    rl.acquire()
    print(current_thread().name, "抢到了锁+2")
    rl.release()
    print(current_thread().name, "释放了锁-1")
    rl.release()
    print(current_thread().name, "释放了锁-2")


def run():
    func1()
    func2()


for i in range(10):
    t = Thread(target=run)
    t.start()

同一把递归锁可以在同一线程中被多次acquire()

但是acquire()几次就要释放release()几次

PS: 这把递归锁当被某一线程申请到了

其他线程就无法acquire()了

GIL(全局解释器锁)

在Cpython解释器中有一把GIL锁(全局解释器锁),

GIl锁本质是一把互斥锁。

线程抢的是GIL锁,GIL锁相当于执行权限

导致了同一个进程下,同一时间只能运行一个线程,无法利用多核优势

为什要有GIL锁?

  • 因为cpython自带的垃圾回收机制不是线程安全的,所以要有GIL锁

Semaphore(信号量)

from threading import Thread,Semaphore,current_thread
import time
se = Semaphore(3)
def run():
    se.acquire()
    print(current_thread().name,"抢到了锁")
    time.sleep(0.5)
    se.release()


for i in range(100):

    t = Thread(target=run)
    t.start()

设置互斥锁的数量Semaphore(n)

本质上,当信号量的值为1时 就是互斥锁

同一时刻这把锁可以被申请n次

锁

锁

进程锁

from multiprocessing import Process, Lock
import json,time

def run(lock):
    lock.acquire()
    with open("a.json",'r',) as f:
        res = json.load(f)
        print(res)
    time.sleep(2)

    with open('a.json','w') as fw:
        res['count'] -= 1
        json.dump(res,fw)
    lock.release()

if __name__ == '__main__':
    """解决方案"""
    lock = Lock() # 在这里加一把锁,切记是只有一把锁
    p_l = []
    for i in range(10):

        p =  Process(target=run,args=(lock,))
        p_l.append(p)
        p.start()
    for p in p_l:
        p.join()
    with open('a.json','r') as f:
        print(json.load(f))

from multiprocessing import Lock

  • 导入Lock

lock = Lock()

  • 定义锁对象

lock.acquire()

  • 为你的某一部分代码上锁
  • 注意的是,当这把锁上锁时,其他进程无法运行这部分的代码

lock.release()

  • 解锁
  • 只有解锁后,其他进程才可以抢到这把锁来继续运行自己的代码

注意:在多进程是要确保多个进程使用的是同一把锁

XMind: ZEN - Trial Version锁

上一篇:谈谈高并发系统的限流


下一篇:Python-32-多线程2