加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

day34:线程&守护线程&线程锁&事件

发布时间:2020-12-20 09:55:58 所属栏目:Python 来源:网络整理
导读:目录 1.线程的基本使用 2.用类定义线程 3.线程相关的函数 4.守护线程 5.线程中安全问题:Lock 6.信号量:Semaphore 7.死锁 互斥锁 递归锁 8.事件:Event 线程的基本使用 首先,明确一下线程和进程的定义 进程 :资源分配的最小单位 线程 :cpu执行程序的最小单位

目录

1.线程的基本使用

2.用类定义线程

3.线程相关的函数

4.守护线程

5.线程中安全问题:Lock

6.信号量:Semaphore

7.死锁 互斥锁 递归锁

8.事件:Event

线程的基本使用

首先,明确一下线程和进程的定义

进程:资源分配的最小单位

线程:cpu执行程序的最小单位

1.一个进程资源中可以包含多个线程

def func(num):
    time.sleep(random.uniform(0.1,1))
    print("当前进程{},参数是{}".format(os.getpid(),num))


for i in range(10): # 在一个进程资源中创建了十个线程
    t = Thread(target=func,args=(i,))
    t.start()

print(os.getpid())

运行结果如下图所示

2.并发的多线程和多进程谁的速度快? 多线程!

计算多线程执行时间

 func(num):
    if __name__ == __main__:
     多线程
    lst = []
     记录开始时间
    startime = time.time()
    in range(1000):
        t = Thread(target=func,))
        t.start()
        lst.append(t)

     等到所有的子线程执行完毕
    in lst:
        i.join()

     计算结束时间
    endtime =多线程执行时间",(endtime - startime))  0.27

如图所示,跑1000个线程只需要0.27s

计算多进程执行时间

:
    lst = []
    startime =):
        t = Process(target=func,1)">多进程执行时间 63.30

如图所示,跑1000个进程需要63.30s

所以,我们得出结论!并发的多线程要远比多进程快!!!

3.多线程之间,共享同一份进程资源

num = 1000
 func():
    global num
    num -= 1
    
):
    t = Thread(target=func)
    t.start()
    
print(num)
    

运行结果如下图所示

用类定义线程

class MyThread(Thread):
    def __init__(self,name):
         手动调用父类的构造方法
        super().()
        self.name = name
        
     run(self):
        time.sleep(1)
        当前进程号码是{},名字是{}:
    t = MyThread(当前是一个线程)
    t.start()
    主线程执行结束 ... ")

线程相关的函数

1.线程.is_alive() 检测线程是否仍然存在

2.线程.setName() 设置线程名字

3.线程.getName() 获取线程名字

 func():
    time.sleep(1)

:
    t = Thread(target=func)
    t.start()
     检测线程是否仍然存在
    print(t.is_alive())  True
     获取线程名字
    print(t.getName())   Thread-1
     设置线程名字
    t.setName(xboyww)
    print(t.getName())  xboyww

1.currentThread().ident 查看线程id号

子线程的线程id{}.format(currentThread().ident))

:
    Thread(target=func).start()
    主线程的线程id{}".format(currentThread().ident))

运行结果如下图所示

2.enumerate() 返回目前正在运行的线程列表

3.activeCount() 返回目前正在运行的线程数量

.format(currentThread().ident))
    time.sleep(0.5)


in range(10):
        Thread(target=func).start()
    lst = enumerate()
     主线程 + 10个子线程
    (lst,len(lst))

     3.activeCount() 返回目前正在运行的线程数量
    print(activeCount())   11

运行结果如下图所示

守护线程

守护线程和守护进程不同

守护进程是守护主进程,主进程结束,守护进程立刻被杀死

守护线程是守护所有线程,必须等所有线程结束,守护线程才会被杀死

 func1():
    while True:
        time.sleep(0.5我是func1 func2():
    我是func2 start ... )
    time.sleep(3我是func2 end ...  func3():
    我是func3 start ... )
    time.sleep(5我是func3 end ... :
    t1 = Thread(target=func1)
    t2 = Thread(target=func2)
    t3 = Thread(target=func3)
    
     在start调用之前,设置线程为守护线程
    t1.setDaemon(True)
    
    t1.start()
    t2.start()
    t3.start()
    
    主线程执行结束 .... ")

运行结果如下图所示

线程中安全问题:Lock

现在,我们想完成如下的操作:

  1.在线程p1中for循环100万次,每次完成一次+1操作

  2.在线程p2中for循环100万洗,每次完成一次-1操作

根据想法,我们可以写出如下代码:

n = 0


 func1(lock):
     n
    in range(1000000):
        n += 1


 lock.release()

 func2(lock):
    ):
        n -= 1


 []
    lock = Lock()

    startime =):
        t1 = Thread(target=func1,1)">(lock,))
        t2 = Thread(target=func2,))
        t1.start()
        t2.start()
        lst.append(t1)
        lst.append(t2)

     lst:
        i.join()

    endtime =主线程执行结束 ...  打印{} 时间是{}".format(n,endtime - startime))

执行结果如下图所示

然而,这并不是我们想要的结果

所以我们需要在线程t1和线程t2加锁

运行代码,发现得到的结果正是我们想要的结果

信号量:Semaphore

线程的Semaphore和进程的Semaphore完全一致,在此就不过多赘述了

 func(i,sm):
     上锁 + 解锁
    with sm:
        (i)
        time.sleep(3)    
 支持同一时间,5个线程上锁
    sm = Semaphore(5in range(20):
        Thread(target=func,sm)).start()
    
"""
再创建线程的时候是异步创建
在执行任务时,遇到Semaphore进行上锁,会变成同步程序
"""

死锁 互斥锁 递归锁

1.语法上的死锁

只上锁不解锁,一定会产生死锁

lock = Lock()
lock.acquire()
lock.acquire()
lock.acquire()  只上锁不解锁,会产生死锁。运行程序会发生阻塞

lock.release()
print(1)

2.逻辑上的死锁

noodle_lock = Lock()
kuaizi_lock = Lock()


 eat1(name):
    noodle_lock.acquire()
    %s 抢到面条了" % (name))
    kuaizi_lock.acquire()
    %s 抢到筷子了 (name))

    开始享受面条 ... )
    time.sleep(0.5)

    kuaizi_lock.release()
    %s 放下筷子 (name))
    noodle_lock.release()
    %s 放下面条 (name))


 eat2(name):
    kuaizi_lock.acquire()
     (name))
    noodle_lock.acquire()
    )

    noodle_lock.release()
     (name))
    kuaizi_lock.release()
    :
    name_lst1 = [FlyHurt]
    name_lst2 = [AlanCat]

    for name  name_lst1:
        Thread(target=eat1,1)">(name,)).start()

     name_lst2:
        Thread(target=eat2,args=(name,)).start()

运行结果如下图所示

3.递归锁

上方的示例造成了逻辑上的死锁现象

想要解决这种情况,我们需要递归锁。

什么是递归锁?

  递归锁专门用来解决这种死锁现象

  临时用于快速解决线上项目发生阻塞死锁问题的

from threading import RLock

rlock = RLock()
rlock.acquire()
rlock.acquire()
rlock.acquire()
rlock.acquire()
print(112233)
rlock.release()
rlock.release()
rlock.release()
rlock.release()

程序结束 ... ")

运行结果如下图所示

4.用递归锁解决2中(面条-筷子)的死锁现象

noodle_lock = kuaizi_lock = RLock()

 (name))

5.用互斥锁解决2中(面条-筷子)的死锁现象

用互斥锁解决问题,换句话来说,就是尽量用一把锁解决问题

mylock = Lock()
 eat1(name):
    mylock.acquire()
     (name))
     (name))
    
    )    

     (name))
    mylock.release()

 eat2(name):
    mylock.acquire()
     (name))    
    :
    
    name_lst1 = [ABCD]
    
    

事件:Event

e = Event()

wait 动态添加阻塞

clear 将内部的阻塞值改成False

set 将内部的阻塞值改成True

is_set 获取内部的阻塞值状态(True False)

基本语法

e = Event()
(e.is_set())
e.set()
(e.is_set())
e.clear()
(e.is_set())
 代表最多阻塞3秒
e.wait(3)
程序运行中... ")

模拟链接远程数据库

 check(e):
     用一些延迟来模拟检测的过程
    time.sleep(random.randrange(1,6))  1 2 3 4 5
     time.sleep(1)
    开始检测链接用户的合法性)
    e.set()
    
    
 connect(e):
    sign = False
    in range(1,4):  1 2 3    
         设置最大等待1秒
        e.wait(1)    
    
        if e.is_set():
            数据库链接成功 ... )
            sign = True
            break
        else:
            尝试链接数据库第%s次失败 ...  (i))
            
    if sign == False:
         主动抛出异常,(超时异常)
        raise TimeoutError
        
e = 线程1号负责执行连接任务
Thread(target=connect,1)">(e,)).start()

 线程2号负责执行检测任务
Thread(target=check,args=(e,)).start()

运行结果如下图所示

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读