多线程讲解

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.
原文地址:https://www.cnblogs.com/1a2a/p/7448744.html