python并发编程之线程(创建线程,锁(死锁现象,递归锁),GIL锁)

本文介绍了Python中的线程概念,包括进程与线程的区别、线程的创建方式以及线程之间的资源共享。详细讲解了线程锁的使用,通过示例展示了普通锁和递归锁在解决数据安全问题上的应用。同时提到了死锁现象及其避免方法,并讨论了守护线程的特点。最后,简要提及了GIL锁在Python解释器中的作用。
摘要由CSDN通过智能技术生成

什么是线程

进程:资源分配单位。

线程:cpu执行单位(实体),每一个py文件中就是一个进程,一个进程中至少有一个线程。

线程的两种创建方式

1.方式一

from threading import Thread
def f1(n):
    print(n,'号线程')

if __name__ == '__main__':
    t1 = Thread(target=f1,args=(1,))
    t1.start()
    print('主线程') 

2.方式二

from threading import Thread
class MyThread(Thread):
    def __init__(self,name):
        super().__init__()
        self.name = name

    def run(self):
        print('hello:' + self.name)

if __name__ == '__main__':

    t = MyThread('haha')
    t.start()
    print('主线程结束')

线程的创建和销毁,相对于进程来说开销特别小

线程之间资源共享,共享的是同一个进程中的资源, 资源共享就涉及到数据安全问题,加锁来解决。

线程锁

使用原型

From threading import Thread,Lock

def f1: 

  Loc.acquire()

  代码

  Loc.release()

main

  Loc = Lock()

  T = thread(target=f1,args=(loc,)

使用示例

from multiprocessing import Queue
import queue
import time
from threading import Lock,Thread

num = 100
def f1(loc):
    loc.acquire()
    global num
    tmp = num
    tmp -= 1
    time.sleep(0.001)
    num = tmp
    loc.release()

if __name__ == '__main__':

    t_loc = Lock()
    t_list = []
    for i in range(10):
        t = Thread(target=f1,args=(t_loc,))
        t.start()
        t_list.append(t)
    [tt.join() for tt in t_list]
    print('主线的num',num)

锁特点

:牺牲了效率,保证了数据安全

死锁现象(天长地久,永不分离)

出现在锁嵌套的时候,双方互相抢对方已经拿到的锁,导致双方互相等待,这就是死锁现象

import time
from threading import Thread,Lock,RLock

def f1(locA,locB):
    locA.acquire()
    print('f1>>1号抢到了A锁')
    time.sleep(1)
    locB.acquire()
    print('f1>>1号抢到了B锁')
    locB.release()

    locA.release()
def f2(locA,locB):
    locB.acquire()

    print('f2>>2号抢到了B锁')

    locA.acquire()
    time.sleep(1)
    print('f2>>2号抢到了A锁')
    locA.release()

    locB.release()
if __name__ == '__main__':
    locA = Lock()
    locB = Lock()
    t1 = Thread(target=f1,args=(locA,locB))
    t2 = Thread(target=f2,args=(locA,locB))
    t1.start()
    t2.start()

递归锁–解决死锁现象

Rlock 首先本身就是个互斥锁,维护了一个计数器,每次acquire就+1,release就-1,当计数器为0的时候,大家才能抢这个锁。

import time
from threading import Thread, Lock, RLock

def f1(locA, locB):
    locA.acquire()
    print('f1>>1号抢到了A锁')
    time.sleep(1)
    locB.acquire()
    print('f1>>1号抢到了B锁')
    locB.release()
    locA.release()

def f2(locA, locB):
    locB.acquire()
    print('f2>>2号抢到了B锁')
    locA.acquire()
    time.sleep(1)
    print('f2>>2号抢到了A锁')
    locA.release()
    locB.release()

if __name__ == '__main__':

    locA = locB = RLock()  
    t1 = Thread(target=f1, args=(locA, locB))
    t2 = Thread(target=f2, args=(locA, locB))
    t1.start()
    t2.start()

守护线程:

守护线程:等待所有非守护线程的结束才结束。
守护进程:主进程代码运行结束,守护进程就随之结束。

import time
from threading import Thread
from multiprocessing import Process

def f1():
    time.sleep(2)
    print('1号线程')
def f2():
    time.sleep(3)
    print('2号线程')

if __name__ == '__main__':
    t1 = Thread(target=f1,)
    t2 = Thread(target=f2,)
    t2.daemon = True
    t1.start()
    t2.start()
    print('主线程结束')

GIL锁 :

cpython解释器上的一把互斥锁,当线程需要进入cpu做运算时必须一个一个经过GIL锁。
  在这里插入图片描述
线程的事件,信号量 与进程的事件,信号量 用法相同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值