多线程

目录

1.什么是线程

# 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程
# 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程
# 车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一个流水线
# 流水线的工作需要电源,电源就相当于cpu

进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。

多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源

2.线程与进程的区别

1.线程共享创建它的进程的地址空间;进程有自己的地址空间。              
2.线程可以直接访问其进程的数据段;进程有自己的父进程数据段副本。              
3.线程可以直接与其进程的其他线程通信;进程必须使用进程间通信与兄弟进程通信。              
4.新线程很容易创建;新进程需要父进程的重复。              
5.线程可以对同一进程的线程进行相当大的控制;进程只能对子进程进行控制。              
6.对主线程的更改(取消、优先级更改等)可能会影响进程的其他线程的行为;对父进程的更改不会影响子进程。

3.为何要用多线程

多线程指的是,在一个进程中开启多个线程,简单的讲:如果多个任务共用一块地址空间,那么必须在一个进程内开启多个线程。详细的讲分为4点:
1. 多线程共享一个进程的地址空
2. 线程比进程更轻量级,线程比进程更容易创建可撤销,在许多操作系统中,创建一个线程比创建一个进程要快10-100倍,在有大量线程需要动态和快速修改时,这一特性很有用
3. 若多个线程都是cpu密集型的,那么并不能获得性能上的增强,但是如果存在大量的计算和大量的I/O处理,拥有多个线程允许这些活动彼此重叠运行,从而会加快程序执行的速度。
4. 在多cpu系统中,为了最大限度的利用多核,可以开启多个线程,比开进程开销要小的多。(这一条并不适用于python)

4.开启线程的两种方式

4.1第一种方式

from threading import Thread
import time

def task(name):
    print(f'{name} is running')
    time.sleep(1)
    print(f'{name} is gone')
    

if __name__ == '__main__':
    p = Tread(target = task,args = ('小冯',))
    p.start()
    print('===主线程') # 线程是没有主次之分的

4.2第二种

from threading import Thread
import time

class MyThread(Thread):
    
    def __init__(self,name):
        super().__init__()
        self.name = name
        
    def run(self):
        print(f'{self.name} is running')
        time.sleep(1)
        print(f'{self.name} is gone')
        
        
if __name__ == '__main__':
    p = MyThread('小冯')
    p.start()
    print('主===>')

5.多进程与多线程开启的速度区别

5.1多进程

from multiprocessing import Prcess
import os
def task():
    print('子进程')
if __name__ == '__main__':
    p = Process(target = task)
    p.start()
    print('主===>')

5.2多线程

from threading import Thread
import time

def task(name):
    print(f'{name} is running')
    time.sleep(1)
    print(f'{name} is gone')
    

if __name__ == '__main__':
    p = Tread(target = task,args = ('小冯',))
    p.start()
    print('===主线程') # 线程是没有主次之分的

6.进程线程

# 进程
from multiprocessing import Process
import time
import os
def task(name):
    print(f'子进程: {os.getpid()}')
    print(f'主进程: {os.getppid()}')

if __name__ == '__main__':
    p1 = Process(target=task,args=('常鑫',))  # 创建一个进程对象
    p2 = Process(target=task,args=('常鑫',))  # 创建一个进程对象
    p1.start()
    p2.start()
    print(f'==主{os.getpid()}')
    
    
# 线程:
from threading import Thread
import os

def task():
    print(os.getpid())

if __name__ == '__main__':

    t1 = Thread(target=task)
    t2 = Thread(target=task)
    t1.start()
    t2.start()
    print(f'===主线程{os.getpid()}') # os.getpid()只是获取当前的进程号

7.同一进程内线程是共享数据的

from threading import Thread
import os

x = 3
def task():
    global x
    x = 100

if __name__ == '__main__':

    t1 = Thread(target=task)
    t1.start()
    t1.join()
    print(f'===主线程{x}')

# 同一进程内的资源数据对于这个进程的多个线程来说是共享的.

8.线程的其他方法

from threading import Thread,current_thread,enumerare,activeCount
import os
import time

x = 3
def task():
    # print(currentThread())
    time.sleep(1)
    print('666')
print(123)
if __name__ == '__main__':

    t1 = Thread(target=task,name='线程1')
    t2 = Thread(target=task,name='线程2')
    # name 设置线程名
    t1.start()
    t2.start()
    # time.sleep(2)
    # print(t1.isAlive())  # 判断线程是否活着
    # print(t1.getName())  # 获取线程名
    # t1.setName('子线程-1')
    # print(t1.name)  # 获取线程名  ***

    # threading方法
    # print(currentThread())  # 获取当前线程的对象
    # print(enumerate())  # 返回一个列表,包含所有的线程对象
    print(activeCount())  # ***
    print(f'===主线程{os.getpid()}')

9. join 与 守护线程

# join: 阻塞 告知主线程要等待我子线程执行完毕之后再执行主线程

from threading import Thread
import time

def task(name):
    print(f'{name} is running')
    time.sleep(1)
    print(f'{name} is gone')
    
    
if __name__ == '__main__':
    start_time = time.time()
    t1 = Thread(target = task,args = ('小冯',))
    t2 = Thread(target = task,args = ('小冯1',))
    t3 = Thread(target = task,args = ('小冯2',))
    
    t1.start()
    t2.start()
    t3.start()
    
    print(f'===主线程{time.time() - start_time}') # 线程是没有主次之分的
    
    
# --------------------------------------------------- 
# 守护线程
# 回忆一下守护进程

from multiprocessing import Process
import time

def foo():
    print(123)
    time.sleep(1)
    print("end123")

def bar():
    print(456)
    time.sleep(2)
    print("end456")

if __name__ == '__main__':

    p1 = Process(target=foo,)
    p2 = Process(target=bar,)

    p1.daemon = True
    p1.start()
    p2.start()
    print('====主')
    
# ---------------------------------------------------   
# 守护线程

from threading import Thread
import time

def sayhi(name):
    print('你滚!')
    time.sleep(2)
    print('%s say hello' %name)

if __name__ == '__main__':
    t = Thread(target=sayhi,args=('egon',))
    # t.setDaemon(True) #必须在t.start()之前设置
    t.daemon = True
    t.start()  # 线程的开启速度要跟进程开很多

    print('主线程')
    

# ---------------------------------------------------
from threading import Thread
import time

def foo():
    print(123)  # 1
    time.sleep(1)
    print("end123")  # 4

def bar():
    print(456)  # 2
    time.sleep(3)
    print("end456")  # 5

t1=Thread(target=foo)
t2=Thread(target=bar)

t1.daemon=True
t1.start()
t2.start()
print("main-------")  # 3


# ---------------------------------------------------
# 主线程什么时候结束???
# 守护线程 等待非守护子线程以及主线程结束之后,结束.
from threading import Thread
import time

def foo():
    print(123)  # 1
    time.sleep(3)
    print("end123")  # 4

def bar():
    print(456)  # 2
    time.sleep(1)
    print("end456")  # 5


t1=Thread(target=foo)
t2=Thread(target=bar)

t1.daemon=True
t1.start()
t2.start()
print("main-------")  # 3

# ---------------------------------------------------
from threading import Thread
import time

def foo():
    print(123)
    time.sleep(3)
    print("end123")

def bar():
    print(456)
    time.sleep(1)
    print("end456")


t1=Thread(target=foo)
t2=Thread(target=bar)

t1.daemon=True
t1.start()
t2.start()
print("main-------")

10. 互斥锁

from threading import Thread
import time
import random
x = 100

def task():
    time.sleep(random.randint(1,2))
    global x
    temp = x
    temp = temp - 1
    x = temp

if __name__ == '__main__':
    l1 = []
    for i in range(100):
        t = Thread(target=task)
        l1.append(t)
        t.start()

    for i in l1:
        i.join()
    print(f'主线程{x}')

    
    
    
# 多个任务公抢一个数据,保证数据的安全的目的,要让其串行
from threading import Thread
from threading import Lock
import time
import random
x = 100

def task(lock):

    lock.acquire()
    # time.sleep(random.randint(1,2))
    global x
    temp = x
    time.sleep(0.01)
    temp = temp - 1
    x = temp
    lock.release()


if __name__ == '__main__':
    mutex = Lock()
    l1 = []
    for i in range(100):
        t = Thread(target=task,args=(mutex,))
        l1.append(t)
        t.start()

    time.sleep(3)
    print(f'主线程{x}')
    原文作者:626
    原文地址: https://www.cnblogs.com/fengqiang626/p/11394876.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞