zoukankan      html  css  js  c++  java
  • PythonStudy——线程 Thread

    线程 

    线程是操作系统中最小的运算调度单元,被包含在进程中,一个线程就是一个固定的执行流程

    线程和进程的关系

    线程不能单独存在 必须存在于进程中,

    ​进程是一个资源单位,其包含了运行程序所需的所有资源

    ​线程才是真正的执行单位

    ​没有线程,进程中的资源无法被利用起来,所以一个进程至少包含一个线程,称之为主线程

    当我们启动一个程序时,操作系统就会自己为这个程序创建一个主线程

    ​线程可以由程序后期开启 ,自己开启线程称之为子线程

    为什么需要线程

    目的只有一个,为了提高效率

    就像一个车间 如果产量更不上 就在造一条流水线

    ​ 当然可以再造一个新车间,那需要把原材料运过去 ,这个过程是非常耗时的

    ​ 所以通常情况是创建新的流水线 而不是车间 即 线程

    如何使用线程

    使用方法和多进程一模一样

    ​ 不过开启线程的代码可以放在任何位置 开启进程必须放在判断下面

    from threading import Thread,current_thread
    import time
    
    def task():
        print("2",current_thread())
        print("子线程running")
        time.sleep(10)
        print("子线程over")
    
    # 使用方法一  直接实例化Thread类
    if __name__ == '__main__':
        t = Thread(target=task)
        t.start()
        
        # task()
        # 执行顺序不固定 如果开启线程速度足够快  可能子线程先执行
        print("主线程over")
        print("1",current_thread())
    
    # 使用方法二 继承Thread 覆盖run方法
    class MyThread(Thread):
        def run(self):
            print("子线程run!")
    m = MyThread()
    print("主线over")

    线程的特点

    1.创建开销小

    2.同一个进程中的多个线程数据是共享

    3.多个线程之间,是平等的,没有父子关系 所有线程的PID都是相同的

    守护线程

    一个线程可以设置为另一个线程守护线程

    ​ 特点: 被守护线程结束守护线程也随之结束

    除了主线程之外 还有别的非守护,守护线程等到所有非守护线程结束结束
    如果守护线程已经完成任务 立马就结束了!

    from threading import Thread
    import time
    
    def task():
        print("子1running......")
        time.sleep(100)
        print("子1over......")
    
    def task2():
        print("子2running......")
        time.sleep(4)
        print("子2over......")
        
    t = Thread(target=task)
    t.daemon = True
    t.start()
    
    t2 =Thread(target=task2)
    t2.start()
    
    print("主over")

      

    线程 互斥锁

    共享意味着竞争

    ​线程中也存在安全问题,

    多线程可以并发执行,一旦并发了并且访问了同一个资源就会有问题

    解决方案:还是互斥锁

    from threading import Thread,enumerate,Lock
    import time
    
    number = 10
    
    lock = Lock()
    
    def task():
        global number
        lock.acquire()
        a = number
        time.sleep(0.1)
        number = a - 1
        lock.release()
    
    for i in range(10):
        t = Thread(target=task)
        t.start()
    
    for t in enumerate()[1:]:
        # print(t)
        t.join()
        
    print(number)
    # 输出: 0

    死锁

    from threading import Lock, current_thread, Thread
    
    """
        死锁问题
        当程序出现了不止一把锁,分别被不同的线程持有, 有一个资源 要想使用必须同时具备两把锁
        这时候程序就会进程无限卡死状态 ,这就称之为死锁
        例如:
            要吃饭 必须具备盘子和筷子   但是一个人拿着盘子 等筷子  另一个人拿着筷子等盘子
        
        如何避免死锁问题  
            锁不要有多个,一个足够
            如果真的发生了死锁问题,必须迫使一方先交出锁
            
    """
    import time
    # 盘子
    lock1 = Lock()
    
    # 筷子
    lock2 = Lock()
    
    def eat1():
        lock1.acquire()
        print("%s抢到了盘子" % current_thread().name)
        time.sleep(0.5)
        lock2.acquire()
        print("%s抢到了筷子" % current_thread().name)
    
        print("%s开吃了!" % current_thread().name)
        lock2.release()
        print("%s放下筷子" % current_thread().name)
    
        lock1.release()
        print("%s放下盘子" % current_thread().name)
    
    
    def eat2():
        lock2.acquire()
        print("%s抢到了筷子" % current_thread().name)
    
        lock1.acquire()
        print("%s抢到了盘子" % current_thread().name)
    
    
        print("%s开吃了!" % current_thread().name)
    
    
        lock1.release()
        print("%s放下盘子" % current_thread().name)
        lock2.release()
        print("%s放下筷子" % current_thread().name)
    
    
    t1 = Thread(target=eat1)
    
    
    t2 = Thread(target=eat2)
    
    t1.start()
    t2.start()

    可重入锁 

    Rlock 称之为递归锁或者可重入锁 Reload Lock

    Rlock不是用来解决死锁问题的

    与Lock唯一的区别:
    Rlock同一线程可以多次执行acquire 但是执行几次acquire就应该对应release几次

    如果一个线程已经执行过acquire 其他线程将无法执行acquire

    from threading import RLock, Lock, Thread
    
    # l = Lock()
    #
    # l.acquire()
    # print("1")
    # l.acquire()
    # print("2")
    
    
    l = RLock()
    
    # l.acquire()
    # print("1")
    # l.acquire()
    # print("2")
    
    def task():
        l.acquire()
        print("子run......")
        l.release()
    
    
    # 主线程锁了一次
    l.acquire()
    l.acquire()
    
    l.release()
    l.release()
    t1 = Thread(target=task)
    t1.start()

    信号量

    可以现在被锁定的代码 同时可以被多少线程并发访问
    Lock 锁住一个代码块 同时只能有一个线程访问
    Semaphore 锁住一个代码块    同时可以来一堆线程访问

    用途: 仅用于控制并发访问 并不能防止并发修改造成的问题

    from threading import Semaphore, Thread
    import time
    
    s = Semaphore(5)
    def task():
        s.acquire()
        print("子run")
        time.sleep(3)
        print("子over")
        s.release()
    
    for i in range(10):
        t = Thread(target=task)
        t.start()

     线程的常用方法

    from threading import Thread
    from threading import current_thread
    from threading import enumerate
    from threading import active_count
    
    
    # 获取当前线程(主线程)对象
    print(current_thread())
    # <_MainThread(MainThread, started 140735554691968)>
    
    # 获取当前线程(主线程)对象所属的类名
    print(current_thread().__class__)
    # <class 'threading._MainThread'>
    
    def task():
        print(current_thread())
        # <Thread(Thread-1, started 123145537966080)>
    
        # 获取正常运行的所有线程对象(列表存储)
        print(enumerate())
        # [<_MainThread(MainThread, started 140735554691968)>,
        # <Thread(Thread-1, started 123145411694592)>]
    
        print(current_thread().__class__)
        # <class 'threading.Thread'>
    
        # 获取存活的线程数量
        print(active_count())
        # 2
    
        # 获取当前进程的名称 其他属性进程对象差不多
        print(current_thread().getName())
        # Thread-1
    
    # 创建子线程
    thread1 = Thread(target=task)
    # 启动子线程
    thread1.start()
    # 获取当前进程的名称 其他属性进程对象差不多
    print(current_thread().getName())
    # MainThread
  • 相关阅读:
    Spring Security【一】 ------ 前后端分离开发
    mybatis 使用mybatis-plus-generator进行代码自动生成
    VuejsApp简介
    BeetleX之Vue ElementUI生成工具
    BeetleX数据分析中间服务V3
    vuejs集成echarts的一些问题
    BeetleX使用bootstrap5开发SPA应用
    BeetleX大数据之产品分析服务
    小试牛刀ElasticSearch大数据聚合统计
    在windows 10的ubuntu系统上如何使用dd命令写u盘?
  • 原文地址:https://www.cnblogs.com/tingguoguoyo/p/10976386.html
Copyright © 2011-2022 走看看