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

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

# 并发:是指系统具有处理多个任务(动作)的能力
# 并行:是指系统具有 同时 处理多个任务(动作)的能力

# 同步:当进程执行到一个IO(等待外部数据)的时候,需要等待外部数据接收完
# 异步:当进程执行到一个IO(等待外部数据)的时候,不需要等待外部数据接收完,还可以做其它的处理

# GIL: 全局解释器锁 在python中,无论你启多少个线程,你有多少个cpu,python在执行的时候在同一时刻只请允许一个线程运行
# 任务:IO密集型(python的多线程是有意义的,或使用多进程+协程) 计算密集型(python的多线程就不推荐,python就不适用了)

# 同步锁
import threading, time

num = 100

def sub():
    global num
    temp = num
    time.sleep(0.00001)
    num = temp - 1

l = []  # 定义一个空列表
for i in range(100):  # 循环100次
    t = threading.Thread(target=sub)  # 通过循环创建100个线程t对象并放入列表中
    t.start()
    l.append(t)

for t in l:  # 循环列表,让每一个线程对象t执行join()
    t.join()

print(num)  # 99 居然不是0,问题在哪里?

# 因为此时是IO操作,当第一个线程取到100后要睡1秒,这时还没有减1,这时第二个线程又来取值,值还是100,只要cpu执行速度越快,所有的线程来取值时都是100,意味着100个线程都拿到num为100
# 如果sleep(0.00001),这时最终值又会变为92。这里的值与cpu调度的各线程IO操作的时间有关,sleep时间越短,各个线程拿到num为100时的情况就越少
# 解决方法,加上同步锁,在同一时间只允许一个线程对num操作
import threading, time

num = 100

def sub():
    global num

    lock.acquire()  # 加锁
    temp = num
    time.sleep(0.00001)
    num = temp - 1
    lock.release()  # 解锁

l = []  # 定义一个空列表
lock = threading.Lock()  # 创建同步锁
for i in range(100):  # 循环100次
    t = threading.Thread(target=sub)  # 通过循环创建100个线程t对象并放入列表中
    t.start()
    l.append(t)

for t in l:  # 循环列表,让每一个线程对象t执行join()
    t.join()

print(num)  # 0

# 一个死锁的例子 第一个线程需要A锁(A锁已被第二个线程占用),第二个线程需要B锁(B锁已被第一个线程占用)。结果谁也不让造成死锁
import threading, time

class MyThread(threading.Thread):

    def actionA(self):
        A.acquire()
        print(self.name, ‘gotA‘, time.ctime())
        time.sleep(2)
        B.acquire()
        print(self.name, ‘gotB‘, time.ctime())
        time.sleep(2)
        B.release()
        A.release()

    def actionB(self):
        B.acquire()
        print(self.name, ‘gotB‘, time.ctime())
        time.sleep(2)
        A.acquire()
        print(self.name, ‘gotA‘, time.ctime())
        time.sleep(2)
        A.release()
        B.release()

    def run(self):
        self.actionA()
        self.actionB()

if __name__ == ‘__main__‘:
    A = threading.Lock()
    B = threading.Lock()

    l = []
    for i in range(5):
        t = MyThread()
        t.start()
        l.append(t)

    for i in l:
        t.join()
    print(‘end...‘)

# 解决死锁的方案,使用递归锁

import threading, time

class MyThread(threading.Thread):

    def actionA(self):
        r_lock.acquire()
        print(self.name, ‘gotA‘, time.ctime())
        time.sleep(2)
        r_lock.acquire()
        print(self.name, ‘gotB‘, time.ctime())
        time.sleep(2)
        r_lock.release()
        r_lock.release()

    def actionB(self):
        r_lock.acquire()
        print(self.name, ‘gotB‘, time.ctime())
        time.sleep(2)
        r_lock.acquire()
        print(self.name, ‘gotA‘, time.ctime())
        time.sleep(2)
        r_lock.release()
        r_lock.release()

    def run(self):
        self.actionA()
        self.actionB()

if __name__ == ‘__main__‘:
    r_lock = threading.RLock()  # 这里创建的是递归锁,将原来的两把锁AB换成一把锁
    # 哪个线程拿到r_lock锁,只有等它完全释放后,其它的线程才能再拿这个锁

    l = []
    for i in range(5):
        t = MyThread()
        t.start()
        l.append(t)

    for i in l:
        t.join()

    print(‘end...‘)

原文地址:https://www.cnblogs.com/dangrui0725/p/9496031.html

时间: 2024-08-02 16:53:36

并发&并行 同步&异步 GIL 任务 同步锁 死锁 递归锁的相关文章

同步锁 死锁 递归锁

多线程 同步锁(互斥锁) 解决什么问题? 同步锁解决什么问题? 多个线程操作同一个数据,可能会发生数据错乱的问题,因为一个线程拿到数据后,还没来得及对数据进行操作,cpu就有可能去执行另外一个线程,另外一个线程拿到的则是之前线程没有处理完的数据,如下 import threading import time count=20 def zx(): global count print(count) time.sleep(0.001) count-=1 t_list=[] for t in rang

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

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

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

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

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

线程(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并发编程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.昨日回顾 #生产者消

并发编程---死锁||递归锁---信号量---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):

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并发编程之多线程2------------死锁与递归锁,信号量等

一.死锁现象与递归锁 进程也是有死锁的 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用, 它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程, 如下就是死锁 1 死锁------------------- 2 from threading import Thread,Lock,RLock 3 import time 4 mutexA = Lock() 5 mutexB = Lock() 6