zoukankan      html  css  js  c++  java
  • 多线程讲解

    1多线程概念

    2多线程的两种开启方式

    3多线程对象的属性或方法

    4join与守护线程

    5守候线程与守候进程

    6GIL与lock

    7线程与进程的区别

    1多线程概念

        在一个进程里开启多个线程,他们共享同一个进程的资源。里面有一个主线程,其余都是其他线程。线程相当于一个车间的流水线,进程相当于一个车间。在进程开启时就会有一个主线程。主线程和新开启的线程共享资源。线程开启的速度很快。

     多线程指的是,在一个进程中开启多个线程,简单的讲:如果多个任务共用一块地址空间,那么必须在一个进程内开启多个线程。详细的讲分为4点:

      1. 多线程共享一个进程的地址空间

          2. 线程比进程更轻量级,线程比进程更容易创建可撤销,在许多操作系统中,创建一个线程比创建一个进程要快10-100倍,在有大量线程需要动态和快速修改时,这一特性很有用

          3. 若多个线程都是cpu密集型的,那么并不能获得性能上的增强,但是如果存在大量的计算和大量的I/O处理,拥有多个线程允许这些活动彼此重叠运行,从而会加快程序执行的速度。

          4. 在多cpu系统中,为了最大限度的利用多核,可以开启多个线程,比开进程开销要小的多。(这一条并不适用于python)

    2多线程的两种开启方式:一个是函数一个是类和共享一个内存空间

    #方法一
    # from threading import Thread
    # from  multiprocessing  import  Process
    # import os
    # def talk():
    #     print('%s is running' %os.getpid())
    #
    # if __name__ == '__main__':
    #     t=Thread(target=talk)
    #     # t=Process(target=talk)
    #     t.start()
    #     print('主')
    
    #方法二
    from threading import Thread
    import os
    class MyThread(Thread):
        def __init__(self,name):
            super().__init__()
            self.name=name
        def run(self):
            print('pid:%s name:[%s]is running' %(os.getpid(),self.name))
    
    if __name__ == '__main__':
        t=MyThread('egon')
        t.start()
        print('',os.getpid())
    和共享一个内存空间
    from threading import Thread
    input_l=[]
    format_l=[]
    def talk():
        while True:
            msg=input('>>: ')
            if not msg:continue
            input_l.append(msg)
    def format():
        while True:
            if input_l:
                res=input_l.pop()
                format_l.append(res.upper())
    def save():
        with open('db.txt','a') as f:
            while True:
                if format_l:
                    f.write('%s
    ' %(format_l.pop()))
                    f.flush()
    
    
    if __name__ == '__main__':
        t1=Thread(target=talk)
        t2=Thread(target=format)
        t3=Thread(target=save)
    
        t1.start()
        t2.start()
        t3.start()

    3多线程对象的属性或方法

    from threading import Thread,currentThread,activeCount
    import os,time,threading
    def talk():
        print('%s is running' %currentThread().getName())#打印的是正在运行的线程的名字
        #
        # print(currentThread().getName())
    
    if __name__ == '__main__':
        # t=Thread(target=talk,name='egon')
        t=Thread(target=talk)#开线程
        t.start()#启动
        print(t.name)#打印线程的名字
        # print(t.getName())#打印线程的名字
        print(t.is_alive())#是否活着
        print(currentThread().getName())#打印主线程的名字
        print(threading.enumerate())#打印有序列表
        # time.sleep(3)
        # print(t.is_alive())#是否活着
        print('',activeCount())#打印目前存活的进程

    4join与守护线程

    from threading import Thread,currentThread
    import time
    def talk():
        time.sleep(2)
        print('%s is running' %currentThread().getName())
    
    if __name__ == '__main__':
        t=Thread(target=talk)
        t.start()
        t.join()#主线程等着子线程
        print('')
    from threading import Thread,currentThread
    import os,time,threading
    def talk1():
        time.sleep(5)
        print('%s is running' %currentThread().getName())
    def talk2():
        time.sleep(10)
        print('%s is running' %currentThread().getName())
    if __name__ == '__main__':
        t1=Thread(target=talk1)
        t2=Thread(target=talk2)
        t1.daemon=True#设置守护线程,主线程挂了它也跟着挂啦
        t1.start()
        t2.start()#
        print('主线程',os.getpid())
    #在这个代码里就会出现t1和t2线程都运行完了,
    # 对于主线程来说什么时候是结束呢?是除了守护线程外其余的线程都运行完了,主线程就结束,顺带着守候进程离开
    from threading import Thread
    import time
    def foo():
        print(123)
        time.sleep(5)
        print("end123")
    
    def bar():
        print(456)
        time.sleep(10)
        print("end456")
    
    if __name__ == '__main__':
        t1=Thread(target=foo)
        t2=Thread(target=bar)
        t1.daemon=True
        t1.start()
        t2.start()
        print("main-------")

    5守候线程与守候进程

    #不管是守护线程还是守候进程:他俩都是守候主线程和父进程的。在主线程和父进程结束的时候就结束了。
    # 主线程的结束标志是:在除了守候线程外其余线程都都结束了,才结束
    #父进程结束的标志是:在父进程代码运行完了就结束啦。

    6GIL与lock

    定义:
    In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple 
    native threads from executing Python bytecodes at once. This lock is necessary mainly 
    because CPython’s memory management is not thread-safe. (However, since the GIL 
    exists, other features have grown to depend on the guarantees that it enforces.)
    
    '''
    结论:在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势
    #GIL是cyphton的解释器的全局锁,用它运行一个文件时,会产生一个进程和多个线程。通过全局锁来控制解释器里的数据安全性,但是他不保证用户文件的安全性。用户数据也需要用Lock这把锁要控制。
    #文件类型不一样,锁的类型也不一样。

     7线程与进程的区别

    1. Threads share the address space of the process that created it; processes have their own address space.
    2. Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.
    3. Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes.
    4. New threads are easily created; new processes require duplication of the parent process.
    5. Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes.
    6. Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process does not affect child processes.
  • 相关阅读:
    jackson 枚举 enum json 解析类型 返回数字 或者自定义文字 How To Serialize Enums as JSON Objects with Jackson
    Antd Pro V5 中ProTable 自定义查询参数和返回值
    ES6/Antd 代码阅读记录
    es 在数据量很大的情况下(数十亿级别)如何提高查询效率啊?
    Antd Hooks
    使用.Net Core开发WPF App系列教程(其它 、保存控件内容为图片)
    使用.Net Core开发WPF App系列教程( 三、与.Net Framework的区别)
    使用.Net Core开发WPF App系列教程( 四、WPF中的XAML)
    使用.Net Core开发WPF App系列教程( 二、在Visual Studio 2019中创建.Net Core WPF工程)
    使用.Net Core开发WPF App系列教程( 一、.Net Core和WPF介绍)
  • 原文地址:https://www.cnblogs.com/1a2a/p/7448744.html
Copyright © 2011-2022 走看看