• 学习总结(三十四)


    1.线程

        什么是线程

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

    2.线程与进程的关系

             线程不能单独存在必须存在于进程中,进程是一个资源单位,其包含了运行程序所需的所有资源,线程才是真正的执行单位

        没有线程,进程中的资源无法被利用起来,所以一个进程至少包含一个线程,称之为主线程,当我们启动一程序时,操作系统就会为自己这个程序创建一个主线程,线程可以由程序后期开启,自己开启线程称之为子线程

    3.为什么需要线程

                   目的只有一个就是提高效率

    4.多线程的使用方式

         继承Thread类,然后重写run()方法

    from threading import Thread,current_thread
    import time
    
    def task():
        print("2",current_thread())
        print("子进程running")
        time.sleep(10)
        print("子进程")
    
    if __name__ == '__main__':
        t=Thread(target=task)
        t.start()
        print("主线程")
        print("1",current_thread())
    
    class myThread(Thread):
        def run(self):
              print("子进程tun")
    m=myThread()
    print("父进程")
    

     

    5.线程的特点

           1)创建开销小

           2)同一个进程中的多个线程数据可以共享

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

      

    # 创建线程开销对比
    import os
    from threading import  Thread
    from multiprocessing import Process
    
    import time
    
    
    def task():
        # print("hello")
        print(os.getpid())
        pass
    
    if __name__ == '__main__':
    
        st_time = time.time()
    
        ts = []
        for i in range(100):
            t = Thread(target=task)
            # t = Process(target=task)
            t.start()
            ts.append(t)
    
        for t in ts:
            t.join()
    
        print(time.time()-st_time)
        print("主over")
    

      

    6.守护线程

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

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

    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")
    

      

    7.线程 互斥锁

          共享意味着竞争

           线程中也存在安全问题,

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

           解决方案:还是互斥锁

    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)

    8.死锁问题

    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()
    

      

    9.可重入锁

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

          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()
    

      

    10.信号量

    """
     信号量 了解
    Lock  RLock
    
    可以现在被锁定的代码 同时可以被多少线程并发访问
    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()
    

      

  • 相关阅读:
    DBMS_SCHEDULER 的使用
    Android 鲜为人知的 8 个小秘密
    你正在使用的移动电话已经 40 岁
    HDU1056:HangOver
    Firefox OS 源码泄露!!!
    上网本 硬盘安装linux 最揪心的回忆
    103 Stacking Boxes
    ip2long之后有什么好处?
    mysql怎么创建,删除,查看索引?
    用mysql查询某字段是否有索引
  • 原文地址:https://www.cnblogs.com/xzcvblogs/p/10974580.html
Copyright © 2020-2023  润新知