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.
  • 相关阅读:
    armlinuxgnueabihf、aarch64linuxgnu等ARM交叉编译GCC的区别
    《JAVA与模式》之简单工厂模式
    wget常用命令
    sublime text添加Jquery插件
    e = e || window.event用法细节讨论
    配置运行 Compilify.net
    [翻译].NET中的Command(命令)模式
    EF Code First 中使用Jarek Kowalski's Provider的方法1
    WF实例学习笔记:(1)准备工作
    Entity Framework Code First Caching
  • 原文地址:https://www.cnblogs.com/1a2a/p/7448744.html
Copyright © 2011-2022 走看看