zoukankan      html  css  js  c++  java
  • 操作系统/应用程序、操作中的“并发”、线程和进程的区别,线程

    并发编程前言:

          1、网络应用

               1)爬虫 直接应用并发编程;

               2)网络框架 django flask tornado 源码-并发编程

               3)socketserver 源码-并发编程

          2、运维领域

               1)自动化开发-运维开发(机器的批量管理,任务的批量执行等)

    一、操作系统/应用程序

    a、硬件

           - 硬盘

           - CPU

           - 主板

           - 显卡

           - 内存

           - 电源

           . . . . . .

    b、装系统(软件)

           - 系统就是一个由程序员写出来的软件,该软件用于控制计算机的硬件,让他们之间进行相互配合。

    c、安软件(安装应用程序)

           - QQ

           - 百度云

           - pycharm

           . . . . . .

    二、并行与并发

      

    并发:是伪并行,即看起来是同时运行。单个cpu+多道技术就可以实现并发,(并行也属于并发)

     单cpu,多进程并发举例

      并行:并行:同时运行,只有具备多个cpu才能实现并行

     多个cpu、多进程并行举例

    三、线程和进程

    a、单进程、单线程的应用程序,比如:

      print('666')

    b、到底什么是线程?什么是进程?

           python自己没有这玩意,python中调用的操作系统的线程和进程。

    c、单进程、多线程的应用程序,比如:

        import threading
        print('666')
    
        def func(arg):
            print(arg)
        t = threading.Thread(target=func,args=(11,)) # 创建一个线程
        t.start()
    

      一个应用程序(软件),可以有多个进程(默认只有一个),一个进程中可以创建多个线程(默认一个)。

    问题1:为什么有这把GIL锁?

                  python语言的创始人在开发这门语言时,目的是快速把语言开发出来,如果加上GIL锁(c语言加锁),切换时按照100条字节指令来进行线程间的切换。

           问题2:进程和线程的区别?

                  线程,线程是cpu工作的最小单元;

                  进程,进程是cpu资源分配的最小单元,为线程提供一个资源共享的空间;

                  一个进程中可以有多个线程,一个进程中默认有一个主线程;

                  对于python来说,它的进程和线程和其他语言有差异,有GIL锁。它保证一个进程中同一时刻只有一个线程被cpu调度;

                  IO密集型操作可以使用多线程,计算密集型可以使用多进程;

      问题3:线程创建的越多越好吗?

                  不是,线程之间进行切换,要做上下文管理。

     线程和进程的效率对比:线程的效率非常高,并且线程开启不需要消耗什么资源

     线程的创建

       第一中创建方式:

    threading四ruai顶      Thread死ruai的

    import time
    from threading import Thread
    from multiprocessing import Process
    def func(n):
        print(n)
    
    if __name__ == '__main__':
        # t = Thread(target=func,args=('我是线程',))
        # t.start() #速度非常快
        p = Process(target=func,args=('我是进程',))
        p.start()
        print('主线程结束') 

      第二种创建方式: 函数继承Thread

    class MyThread(Thread):
    
        def run(self):
            print('sb明杰')
    
    if __name__ == '__main__':
        t = MyThread()
        t.start()
        print('主线程结束')
    

      

    同一进程下,线程是资源共享的

    import time
    from threading import Thread
    from multiprocessing import Process
    
    num = 100
    def func():
        global num
        num = 0
    
    if __name__ == '__main__':
        t = Thread(target=func,)
        t.start()
        t.join()
        print(num)
    

      

     线程资源共享数据不安全,通过锁来解决数据不安全的问题,线程模块里面引入的锁

    锁(同步锁互斥锁):保证数据安全,但是牺牲了效率,同步执行锁内的代码

    import time
    from threading import Thread,Lock          Lock(拉客)
    num = 100
    def func(t_lock):
        global num
        # num -= 1
        t_lock.acquire()
        mid = num
        mid = mid - 1
        time.sleep(0.0001)
        num = mid
        t_lock.release()
    if __name__ == '__main__':
        t_lock = Lock() #锁对象(同步锁,互斥锁)
        t_list = []
        for i in range(10):
            t = Thread(target=func,args=(t_lock,))
            t.start()
            t_list.append(t)
        [tt.join() for tt in t_list]
    
        print('主线程>>>',num)  

     解决死锁线程,用递归锁

    互相抢到了对方的需要的锁,导致双方相互等待,程序没法进行

    import time
    from threading import Thread,Lock,RLock  #递归锁
    
    class MyThread(Thread):
    
        def __init__(self,lockA,lockB):
            super().__init__()
            self.lockA = lockA
            self.lockB = lockB
    
        def run(self):
            self.f1()
            self.f2()
        def f1(self):
    
            self.lockA.acquire()
            print('我拿了A锁')
    
            self.lockB.acquire()
            print('我是一个很好的客户!')
            self.lockB.release()
    
            self.lockA.release()
    
        def f2(self):
            self.lockB.acquire()
            time.sleep(0.1)
            print('我拿到了B锁')
            self.lockA.acquire()
            print('我是一名合格的技师')
            self.lockA.release()
    
            self.lockB.release()
    
    
    if __name__ == '__main__':
        # lockA = Lock()
        # lockB = Lock()
        # lockA = lockB = Lock() #不要这么写,别自己玩自己,锁自己
        lockA = lockB = RLock()
    
        t1 = MyThread(lockA,lockB)
        t1.start()
    
        t2 = MyThread(lockA,lockB)
        t2.start()
    
        print('我是经理')  

     线程进程效率对比

    import time
    from threading import Thread
    from multiprocessing import Process
    
    def func(n):
        num = 0
        for n1 in range(n):
            num += n1
        print('num',num)
    if __name__ == '__main__':
        t_s_t = time.time()
        t_list = []
        for i in range(10):
            t = Thread(target=func,args=(10,))
            t.start() #速度非常快
            t_list.append(t)
        [tt.join() for tt in t_list]
        t_e_t = time.time()
        t_dif_t = t_e_t - t_s_t  #获取了线程的执行时间
    
        p_s_t = time.time() #开始时间
        p_list = []
        for ii in range(10):
            p = Process(target=func,args=(10,))
            p.start()
            p_list.append(p)
        [pp.join() for pp in p_list]
        p_e_t = time.time() #结束时间
        p_dif_t = p_e_t - p_s_t #时间差
    
        print('线程>>>>',t_dif_t)
        print('进程....',p_dif_t)
        print('主线程结束')  

     信号量

       信号量:控制同时能够进入锁内去执行代码的线程数量(进程数量),维护了一个计数器,刚开始创建信号量的时候假如设置的是4个房间,进入一次acquire就加一,出来一次就减一,如果计数器为0的时候,才可以继续抢钥匙,这样其他任务等待,这样的话,其他任务都是同步的状态,而进入acquire里面去执行的那四个任务是异步执行的

    import time
    from threading import Thread, Semaphore
    
    def func1(s):
        s.acquire()
        time.sleep(1)
        print('大宝剑!!!')
        s.release()
    
    if __name__ == '__main__':
        s = Semaphore(4)
        for i in range(10):
            t = Thread(target=func1,args=(s,))
            t.start() 

     主线程等待子线程的原因

    import time
    from threading import Thread
    from multiprocessing import Process
    
    def func(n):
        time.sleep(5)
        print(n)
    
    
    if __name__ == '__main__':
        # 主线程等待的是子线程的任务全部执行完毕
        t = Thread(target=func, args=('我是子线程',))
        t.start()  # 速度非常快
    
        # 主进程等待的是给子进程收尸
        # p = Process(target=func,args=('我是子进程',))
        # p.start()
        # print('主进程结束!!')
        print('主线程结束')
    

    守护线程 

      主线程等待所有非守护进程的结束才结束,主线程的代码运行结束,还要等待守护线的执行完毕,这个过程中守护线程还存在

    守护进程

      主进程代码结束程序并没有结束,并且主进程还存在,进程等待其他的子进程执行结束以后,为子进程收尸,注意一个问题:主进程的代码运行结束守护进程跟着结束,

    代码如下

    import time
    from threading import Thread
    from multiprocessing import Process
    
    def func1(n):
        time.sleep(5)
        print(n)
    def func2(n):
        time.sleep(3)
        print(n)
    
    if __name__ == '__main__':
        # 进程
        p1 = Process(target=func1,args=('我是子进程1号',))
        p1.daemon = True  #设置守护,在start之前加
        p1.start()
        p2 = Process(target=func2, args=('我是子进程2号',))
        p2.start()
    
        t1 = Thread(target=func1, args=('我是子xiancheng1号',))
        t1.daemon = True
        t1.start()
        t2 = Thread(target=func2, args=('我是子xiancheng2号',))
        t2.start()
    
        print('主进程结束!!')
        print('主线程结束')
    

    线程的其他方法 1

    from threading import Thread
    import threading
    import time
    from multiprocessing import Process
    import os
    
    def work():
        import time
        time.sleep(1)
        # print('子线程',threading.get_ident()) #2608
    
    if __name__ == '__main__':
        #在主进程下开启线程
        t=Thread(target=work)    #死如唉的
        t.start()
                current_thread(扣的死如爱的)
        print(threading.current_thread())#主线程对象 #<_MainThread(MainThread, started 1376)>    
        print(threading.current_thread().getName()) #主线程名称 #MainThread
        print(threading.current_thread().ident) #主线程ID #1376
        print(threading.get_ident()) #主线程ID #1376
    
        time.sleep(3)
        print(threading.enumerate())  # 连同主线程在内有两个运行的线程,        enumerate枚举(额牛木蕊特)
        print(threading.active_count()) # 2                   active_count(啊可特康特)
        print('主线程/主进程')

    事件:

    from threading import Thread,Event    Event(一温特)
    
    e = Event()  #e的状态有两种,False True,当事件对象的状态为False的时候,wait的地方会阻塞
    
    e.set()  #将事件对象的状态改为True
    e.clear() #将事件对象的状态改为Flase      clear(克雷尔)
    print('在这里等待')
    e.wait() #阻塞                wait(威特)
    print('还没好!!')
    

      

    线程队列

    队列有三种模式

      先进先出:

    import queue
    q=queue.Queue()
    q.put('first')
    # q.put_nowait() #不等待
    print(q.get())
    q.get_nowait() #没有数据就报错,可以通过try来搞       脑为特

      先进后出:

    import queue
    q=queue.LifoQueue() #队列,类似于栈,栈我们提过吗,是不是先进后出的顺序啊
    q.put('third')
    print(q.get())

      优先级队列:

    import queue
    
    q=queue.PriorityQueue()
    #put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高
    q.put((-10,'a'))
    q.put((-5,'a'))  #负数也可以
    q.put((20,'ws'))  #如果两个值的优先级一样,那么按照后面的值的acsii码顺序来排序,如果字符串第一个数元素相同,比较第二个元素的acsii码顺序
    q.put((20,'wd'))
    q.put((20,{'a':11})) #TypeError: unorderable types: dict() < dict() 不能是字典
    q.put((20,('w',1)))  #优先级相同的两个数据,他们后面的值必须是相同的数据类型才能比较,可以是元祖,也是通过元素的ascii码顺序来排序
    
    '''
    结果(数字越小优先级越高,优先级高的优先出队):
    '''  

    线程池:

    import time
    
    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    from threading import current_thread
    
    def func(n):
        time.sleep(1)
        # print(n,current_thread().ident)
        return n**2
    
    if __name__ == '__main__': 
        t_p = ThreadPoolExecutor(max_workers = 4)        max_workers(马克思我K儿死)
        map_res = t_p.map(func,range(10)) #异步执行的,map自带join功能
        print(map_res)
        print([i for i in map_res])
    

      

    回调函数:

    import time
    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    from threading import current_thread
    
    def func(n):
        time.sleep(1)
        print(n,current_thread().getName())
        return n**2
    
    def func2(n):
        print('>>>>>>>',n.result())
    
    if __name__ == '__main__':
        t_p = ThreadPoolExecutor(max_workers = 4)
        for i in range(3):
            t_p.submit(func,i).add_done_callback(func2)    add_done_callback(俺的 当 考班可)
    
        print('主线程结束')  

    线程池的一些其他方法: 

    ThreadPoolExecutor(死日无爱的  噗奥  A克赛K特)

    ProcessPoolExecutor(噗赛死  噗奥  A克赛K特)

    import time
    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    from threading import current_thread
    
    def func(n):
        time.sleep(1)
        # print(n,current_thread().ident)
        return n**2
    if __name__ == '__main__':
        t_p = ThreadPoolExecutor(max_workers = 4)
        t_res_list = []
        for i in range(10): 
            res_obj = t_p.submit(func,i)#异步提交了10个任务,submit(色卖特)
            t_res_list.append(res_obj)
    
        t_p.shutdown()  #close + join    shutdown(莎当)        close(可篓子)
        for e_res in t_res_list:
            print(e_res.result())#他和get一样  result(蕊造特) 

     多线程和多进程进行纯计算的效率

    import time
    from multiprocessing import Process
    from threading import Thread
    
    def func():
        num = 0
        for i in range(1,10000000):
            num += i
    
    # def func():
    #     time.sleep(2)
    #     print('xxxxxxxx')
    
    if __name__ == '__main__':
        p_s_t = time.time()
        p_list = []
        for i in range(10):
            p = Process(target=func,)
            p_list.append(p)
            p.start()
        [pp.join() for pp in p_list]
        p_e_t = time.time()
        p_dif_t = p_e_t - p_s_t
    
        t_s_t = time.time()
        t_list = []
        for i in range(10):
            t = Thread(target=func,)
            t_list.append(t)
            t.start()
        [tt.join() for tt in t_list]
        t_e_t = time.time()
        t_dif_t = t_e_t - t_s_t
    
        print('多进程执行的时间',p_dif_t)
        print('多线程执行的时间',t_dif_t)
    
    '''
    多进程执行的时间 4.5982630252838135
    多线程执行的时间 8.339477062225342
    '''
    运算

    GIL锁:

     

    并发执行的效率(在没有IO的情况下,两个纯计算的任务 )

    import time
    def func1():
        num2 = 0
        for i in range(1000001):
            num2 += i
            yield
            # print('执行到下一个yield',current_thread().name)
    
    def func2():
        g = func1()
        next(g)
        sum = 0
        for i in range(1000000):
            # g.send(i)
            sum += i
            next(g)
    s_t = time.time()
    func2()
    print('协程的时间',time.time() - s_t)  

     串行执行的效率

    def func1():
        num2 = 0
        for i in range(1000001):
            num2 += i
            # print('执行到下一个yield',current_thread().name)
    
    def func2():
        sum = 0
        for i in range(1000000):
            sum = sum + i
    
    
    s_t = time.time()
    func1()
    func2()
    print('串行的时间',time.time() - s_t)
    
    '''
    协程的时间 0.319796085357666
    串行的时间 0.14291739463806152
    '''
    

      

  • 相关阅读:
    FNV与FNV-1a Hash算法说明【转】
    FNV哈希算法【转】
    git超详细教程【转】
    Git基础篇【转】
    Notepad++中常用的插件【转】
    美化博客园界面(让您的博客更加赏心悦目)希望对您有用【转】
    scanf()总结--从网上收来的,感觉很好,用来提醒自己,c语言真是博大精深!!【转】
    机器人程序设计——之如何正确入门ROS | 硬创公开课(附视频/PPT)【转】
    ROS学习网址【原创】
    机器人操作系统ROS Indigo 入门学习(1)——安装ROS Indigo【转】
  • 原文地址:https://www.cnblogs.com/xihuanniya/p/9856594.html
Copyright © 2011-2022 走看看