同步锁 死锁 递归锁

多线程

同步锁(互斥锁)

解决什么问题?

同步锁解决什么问题?

多个线程操作同一个数据,可能会发生数据错乱的问题,因为一个线程拿到数据后,还没来得及对数据进行操作,cpu就有可能去执行另外一个线程,另外一个线程拿到的则是之前线程没有处理完的数据,如下

import threading
import time
count=20

def zx():

    global count
    print(count)
    time.sleep(0.001)
    count-=1

t_list=[]
for t in range(20):
    t=threading.Thread(target=zx)
    t_list.append(t)
    t.start()

for i in t_list:
    i.join()

print(count)

20
20
20
20
20
20
18
18
18
15
15
15
13
11
11
8
8
8
6
6
0

解决方法

可以强制让cpu执行完一部分代码后,才能去调用其他线程,这样可以确保,其他线程拿到想要的正确数据,但是这一部分是串行的。

具体实现的过程

一.100个线程去抢GIL锁,即抢执行权限

二.肯定有一个线程先抢到GIL(暂且称为线程1),然后开始执行,一旦执行就会拿到lock.acquire()

三.极有可能线程1还未运行完毕,就有另外一个线程2抢到GIL,然后开始运行,但线程2发现互斥锁lock还未被线程1释放,于是阻塞,被迫交出执行权限,即释放GIL

四.直到线程1重新抢到GIL,开始从上次暂停的位置继续执行,直到正常释放互斥锁lock,然后其他的线程再重复2 3 4的过程

import threading
import time
count=20

lock=threading.Lock()

def zx():

    global count
    lock.acquire()
    print(count)
    time.sleep(0.001)
    count-=1
    lock.release()

t_list=[]
for t in range(20):
    t=threading.Thread(target=zx)
    t_list.append(t)
    t.start()

for i in t_list:
    i.join()

print(count)

20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0

死锁

所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁

比如有两个线程,线程1拿到了A锁,但是他只有拿到B锁才能把A锁释放,线程2拿到了B锁,他要拿到A锁才能释放B锁,结果这两个线程就死掉了

import threading
import time

class MyThreading(threading.Thread):

    def run(self):
        self.run1()
        self.run2()

    def run1(self):
        A.acquire()
        print(self.name+"拿到了锁A")
        B.acquire()
        print(self.name+"拿到了锁B")
        B.release()
        print(self.name+"释放了锁B")
        A.release()
        print(self.name+"释放了锁A")

    def run2(self):
        B.acquire()
        print(self.name+"拿到了锁B")
        time.sleep(2)
        A.acquire()
        print(self.name+"拿到了锁A")
        A.release()
        print(self.name+"释放了锁A")
        B.release()
        print(self.name+"释放了锁B")

if __name__ == '__main__':
    A=threading.Lock()
    B=threading.Lock()
    for t in range(5):
        t=MyThreading()
        t.start()

Thread-1拿到了锁A
Thread-1拿到了锁B
Thread-1释放了锁B
Thread-1释放了锁A
Thread-1拿到了锁B
Thread-2拿到了锁A

如何解决死锁

使用递归锁

递归锁

相当于把一块用了很多锁的代码块,看做一个整体,当这个代码块所有的锁都释放了,才能被其他的方法或者线程拿到锁

递归锁的实现原理很简单,当加锁,递归锁的引用计数+1,解锁则-1.当引用计数为0,才能被其他线程或者方法拿到锁。

import threading
import time

class MyThreading(threading.Thread):

    def run(self):
        self.run1()
        self.run2()

    def run1(self):
        D.acquire()
        print(self.name+"D==1")
        D.acquire()
        print(self.name+"D==2")
        D.release()
        print(self.name+"D==1")
        D.release()
        print(self.name+"D==0")

    def run2(self):
        D.acquire()
        print(self.name+"D==1")
        time.sleep(2)
        D.acquire()
        print(self.name+"D==2")
        D.release()
        print(self.name+"D==1")
        D.release()
        print(self.name+"D==0")

if __name__ == '__main__':
    D=threading.RLock()
    for t in range(5):
        t=MyThreading()
        t.start()

这里的==被转义的,将就着看
Thread-1D==1
Thread-1D==2
Thread-1D==1
Thread-1D==0
Thread-1D==1
Thread-1D==2
Thread-1D==1
Thread-1D==0
Thread-2D==1
Thread-2D==2
Thread-2D==1
Thread-2D==0
Thread-2D==1
Thread-2D==2
Thread-2D==1
Thread-2D==0
Thread-4D==1
Thread-4D==2
Thread-4D==1
Thread-4D==0
Thread-4D==1
Thread-4D==2
Thread-4D==1
Thread-4D==0
Thread-3D==1
Thread-3D==2
Thread-3D==1
Thread-3D==0
Thread-5D==1
Thread-5D==2
Thread-5D==1
Thread-5D==0
Thread-5D==1
Thread-5D==2
Thread-5D==1
Thread-5D==0
Thread-3D==1
Thread-3D==2
Thread-3D==1
Thread-3D==0

原文地址:https://www.cnblogs.com/zx125/p/11442945.html

时间: 2024-11-06 14:46:00

同步锁 死锁 递归锁的相关文章

并发&并行 同步&异步 GIL 任务 同步锁 死锁 递归锁

# 并发&并行 同步&异步 GIL 任务 同步锁 死锁 递归锁 # 并发:是指系统具有处理多个任务(动作)的能力 # 并行:是指系统具有 同时 处理多个任务(动作)的能力 # 同步:当进程执行到一个IO(等待外部数据)的时候,需要等待外部数据接收完 # 异步:当进程执行到一个IO(等待外部数据)的时候,不需要等待外部数据接收完,还可以做其它的处理 # GIL: 全局解释器锁 在python中,无论你启多少个线程,你有多少个cpu,python在执行的时候在同一时刻只请允许一个线程运行 #

并发编程8 线程的创建&验证线程之间数据共享&守护线程&线程进程效率对比&锁(死锁/递归锁)

1.线程理论以及线程的两种创建方法 2.线程之间是数据共享的与join方法 3.多线程和多进程的效率对比 4.数据共享的补充线程开启太快 5.线程锁 互斥锁 同步锁 6.死锁现象和递归锁 7.守护线程和守护进程的对比 8.补充 9.GIL锁&GIL锁与线程锁的区别 10.GIL锁补充 11.信号量 时间补充说明 原文地址:https://www.cnblogs.com/studybrother/p/10269278.html

线程的创建 验证线程之间共享数据 守护线程 线程进程效率对比 锁 死锁 递归锁

线程(from threading import Thread):CPU调度的最小单位 线程的两种创建方式:方式一: 1 from threading import Thread 2 def f1(i): 3 print(i) 4 if __name__ == '__main__': 5 for i in range(10): 6 t = Thread(target=f1,args=(i,)) 7 t.start() 8 print('主线程') 方式二: 1 from threading im

python 线程(创建2种方式,守护进程,锁,死锁,递归锁,GIL锁,其他方式)

###############总结############ 线程创建的2种方式(重点) 进程:资源分配单位    线程:cpu执行单位(实体) 线程的创建和销毁的开销特别小 线程之间资源共享,是同一个进程中的资源共享,会涉及到安全问题,所以需要加锁解决 锁:牺牲了效率,保证了数据安全(重点) 死锁现象:出现在嵌套的时候,双方互相抢对方已经拿到的锁,导致双方互相等待(重点) 递归锁: 解决了死锁现象(重点) rlock 首先本身就是个互斥锁,维护了一个计数器,每次acquire+1,release

并发编程---死锁||递归锁---信号量---Event事件---定时器

死锁 互斥锁:Lock(),互斥锁只能acquire一次 递归锁:  RLock(),可以连续acquire多次,每acquire一次计数器+1,只有计数为0时,才能被抢到acquire # 死锁 from threading import Thread,Lock import time mutexA = Lock() mutexB = Lock() class MyThread(Thread): def run(self): self.f1() self.f2() def f1(self):

Python并发编程05/ 死锁/递归锁/信号量/GIL锁/进程池/线程池

目录 Python并发编程05/ 死锁/递归锁/信号量/GIL锁/进程池/线程池 1.昨日回顾 2.死锁现象与递归锁 2.1死锁现象 2.2递归锁 3.信号量 4.GIL全局解释器锁 4.1背景 4.2为什么加锁 5.GIL与Lock锁的区别 6.验证计算密集型IO密集型的效率 6.1 IO密集型 6.2 计算密集型 7.多线程实现socket通信 7.1服务端 7.2客户端 8.进程池,线程池 Python并发编程05/ 死锁/递归锁/信号量/GIL锁/进程池/线程池 1.昨日回顾 #生产者消

ReactiveSwift源码解析(十一) Atomic的代码实现以及其中的Defer延迟、Posix互斥锁、递归锁

本篇博客我们来聊一下ReactiveSwift中的原子性操作,在此内容上我们简单的聊一下Posix互斥锁以及递归锁的概念以及使用场景.然后再聊一下Atomic的代码实现.Atomic主要负责多线程下的原子操作,负责共享资源的同步一致性.而在Atomic中就是使用到了Posix互斥锁和递归锁.在聊上述内容之前,我们先来回顾一下Swift语言中延迟执行defer的使用方式,在之前Swift编程的相关博客中也涉及到了defer的使用方式.defer因为Atomic使用到了延迟操作,所以下方我们再做一个

有关多线程(同步锁,递归锁,同步对象,信号量)

上面一个随笔已经简单介绍了多线程,比如下面在举个简单的例子: 1 #!/usr/bin/env python 2 #-*-coding:utf-8 -*- 3 4 import threading 5 import time 6 7 def add(): 8 sum = 0 9 10 for i in range(1000000): 11 sum += i 12 13 print("sum: ",sum) 14 15 16 def mul(): 17 sum2 = 1 18 for i

python-GIL、死锁递归锁及线程补充

一.GIL介绍 GIL全称 Global Interpreter Lock ,中文解释为全局解释器锁.它并不是Python的特性,而是在实现python的主流Cpython解释器时所引入的一个概念,CIL本质上就是一把互斥锁,将并发运行变成串行,以此来控制同一时间内共享数据只能被一个任务所修改,从而保证数据的安全性. 注:每次执行python程序,都会产生一个独立的进程,进程里除了能看到的若干线程,还有看不见的解释器开启的垃圾回收等解释器级别的线程. #1 所有数据都是共享的,这其中,代码作为一