Python并发编程04/多线程

目录

  • Python并发编程04/多线程

    • 1.生产消费者模型
    • 2.线程的理论知识
      • 2.1什么是线程
      • 2.2线程vs进程
      • 2.3线程的应用
    • 3.开启进程的两种方式
      • 3.1第一种方式
      • 3.2第一种方式
    • 4.线程vs进程的代码对比
      • 4.1开启速度对比
      • 4.2对比pid
      • 4.3同一个进程内线程共享内部数据
    • 5.线程的其他方法
    • 6.join与守护线程
      • 6.1join
      • 6.2守护线程
    • 7.互斥锁

Python并发编程04/多线程

1.生产消费者模型

#编程思想,模型,设计模式,理论等等,都是交给你一种编程的方法,以后你遇到类似的情况,套用即可.
生产者消费者模型三要素:
#   生产者: 产生数据的
#   消费者: 接收数据做进一步处理的
#   容器: 盆(队列)
队列容器的作用:
#起到缓冲的作用,平衡生产力与消费力,解耦.

# from multiprocessing import Process
# from multiprocessing import Queue
# import time
# import random
#
# def producer(q,name):
#     for i in range(1,6):
#         time.sleep(random.randint(1,2))
#         res = f'{i}号包子'
#         q.put(res)
#         print(f'生产者{name} 生产了{res}')
#
#
# def consumer(q,name):
#     while 1:
#         try:
#             food = q.get(timeout=3)
#             time.sleep(random.randint(1, 3))
#             print(f'\033[31;0m消费者{name} 吃了{food}\033[0m')
#         except Exception:
#             return
#
# if __name__ == '__main__':
#     q = Queue()
#     p1 = Process(target=producer,args=(q,'小白'))
#     p2 = Process(target=consumer,args=(q,'小黑'))
#     p1.start()
#     p2.start()

2.线程的理论知识

2.1什么是线程

#一条流水线的工作流程.
#进程: 在内存中开启一个进程空间,然后将主进程的所有的资源数据复制一份,然后调用cpu去执行这些代码.
#之前的描述不够具体:
#开启一个进程:
#在内存中开启一个进程空间,然后将主进程的所有的资源数据复制一份,然后调用线程去执行代码
***进程是资源单位, 线程是执行单位.
标准描述开启一个进程:
    开启一个进程:进程会在内存中开辟一个进程空间,将主进程的资料数据全部复制一份,线程会执行里面的代码.

2.2线程vs进程

#1. 开启进程的开销非常大,比开启线程的开销大很多.
#2. 开启线程的速度非常快.要快几十倍到上百倍.
#3. 同一进程线程与线程之间可以共享数据,进程与进程之间需借助队列等方法实现通信.

2.3线程的应用

#1. 并发: 一个cpu 看起来像是同时执行多个任务.
#   单个进程开启三个线程.并发的执行任务.
#   开启三个进程并发的执行任务.
#   文本编辑器:
#      1. 输入文字.
#      2. 在屏幕上显示.
#      3. 保存在磁盘中.
#
#   开启多线程就非常好了:
#       数据共享, 开销小,速度快.
#主线程子线程没有地位之分,但是,一个进程谁在干活? 一个主线程在干活,当干完活了,你得等待其他线程干完活之后,才能结束本进程.

3.开启进程的两种方式

3.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__':
#
#     t1 = Thread(target=task,args=('二狗',))
#     t1.start()
#     print('===主线程')  # 线程是没有主次之分的.

3.2第一种方式

# from threading import Thread
# import time
#
# class MyThread(Thread):
#
#     def __init__(self,name,l1,s1):
#         super().__init__()
#         self.name = name
#         self.l1 = l1
#         self.s1 = s1
#     def run(self):
#         print(f'{self.name} is running')
#         time.sleep(1)
#         print(f'{self.name} is gone')
#
# if __name__ == '__main__':
#     t1 = MyThread('二狗', [1,2,3], '180')
#     t1.start()
#     print('=====主线程')

4.线程vs进程的代码对比

4.1开启速度对比

多进程

# from threading import Thread
# from multiprocessing import Process
# import os
#
# def work():
#     print('hello')
#
# if __name__ == '__main__':
#     #在主进程下开启线程
#     t=Process(target=work)
#     t.start()
#     print('主线程/主进程')

多线程

# 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__':
#
#     t1 = Thread(target=task,args=('二狗',))
#     t1.start()
#     print('===主线程')  # 线程是没有主次之分的.

4.2对比pid

进程

# 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()}')

4.3同一个进程内线程共享内部数据

# 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}')

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

5.线程的其他方法

# from threading import Thread
# from threading import currentThread
# from threading import enumerate
# from threading import activeCount
# import os
# import time
#
# def task():
#     # print(currentThread())
#     time.sleep(1)
#     print('666')
# 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()}')

6.join与守护线程

6.1join

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()
#     t1.join()
#     t2.start()
#     t2.join()
#     t3.start()
#     t3.join()
#
#     print(f'===主线程{time.time() - start_time}')  # 线程是没有主次之分的.

6.2守护线程

# 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
结果:
123
456
main-------
end123
end456
守护线程 等待非守护子线程以及主线程结束之后,结束.
# 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

7.互斥锁

# from threading import Thread
# import time
# import random
# x = 100
#
# def task():
#     global x
#     temp = x
#     time.sleep(random.randint(1, 3))
#     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()
#
#     for i in l1:
#       i.join()
#     print(f'主线程{x}')

原文地址:https://www.cnblogs.com/liubing8/p/11403483.html

时间: 2024-07-29 06:31:43

Python并发编程04/多线程的相关文章

python并发编程之多线程理论部分

阅读目录 一 什么是线程 二 线程的创建开销小 三 线程与进程的区别 四 为何要用多线程 五 多线程的应用举例 六 经典的线程模型(了解) 七 POSIX线程(了解) 八 在用户空间实现的线程(了解) 九 在内核空间实现的线程(了解) 十 用户级与内核级线程的对比(了解) 十一 混合实现(了解) 一 什么是线程 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 车间负责把资源整合到

python并发编程之多线程2------------死锁与递归锁,信号量等

一.死锁现象与递归锁 进程也是有死锁的 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用, 它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程, 如下就是死锁 1 死锁------------------- 2 from threading import Thread,Lock,RLock 3 import time 4 mutexA = Lock() 5 mutexB = Lock() 6

python并发编程之多线程

一,什么是线程 线程也被称为轻量进程计算机科学术语,指运行中的程序的调度单位. 线程是进程中的实体,一个进程可以拥有多个线程,一个线程必须有一个父进程.线程不拥有系统资源,只有运行必须的一些数据结构:它与父进程的其它线程共享该进程所拥有的全部资源.线程可以创建和撤消线程,从而实现程序的并发执行.一般,线程具有就绪.阻塞和运行三种基本状态. 二,线程与进程的区别 1) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 2) 线程的划分尺度小于进程,使得多线程程序的并发性高. 3) 另外,

python 并发编程之多线程

一.线程理论 1.什么是线程 多线程(即多个控制线程)的概念是,在一个进程中存在多个线程,多个线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源. 所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位. 2.进程与线程的区别 同一进程内的多个线程共享该进程内的地址资源 创建线程的开销要远小于创建进程的开销(创建一个进程,就是创建一个车间,涉及到申请空间,而且在该空间内建至少一条流水线,但创建线程,就只是在一个车间内造一

python并发编程之多线程基础知识点

1.线程理论知识 概念:指的是一条流水线的工作过程的总称,是一个抽象的概念,是CPU基本执行单位. 进程和线程之间的区别: 1. 进程仅仅是一个资源单位,其中包含程序运行所需的资源,而线程就相当于车间的流水线,负责执行具代码. 2. 每个进程至少包含一个线程,由操作系统自动创建,称之为主线程 3. 每个进程可以有任意数量的线程 4.创建进程的开销要比创建进程小得多 5. 同一进程的线程间数据是共享的 6.线程之间是平等的,没有子父级关系,同一进程下的各线程的PID相同 7. 创建线程的代码可以写

python并发编程之多线程(实践篇)

一.threading模块介绍 官网链接:https://docs.python.org/3/library/threading.html?highlight=threading# 1.开启线程的两种方式 #直接调用 import threading import time def run(n): print('task',n) time.sleep(2) t1 = threading.Thread(target=run,args=('t1',)) t1.start() #继承式调用 mport

python并发编程:多线程-线程理论

一 什么是线程 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于CPU),而一条流水线必须属于一个车间,一个车间的工作过程是一个进程,车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一条流水线. 所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是CPU上的执行单位. 多新村(即多个控制线程)的概念时:在一个进程中存在多个线程,多个线程共享该进程的地址空间,

python并发编程:多线程-开启线程的两种方式

一 threading模块介绍 multiprocess模块完全模仿了threading模块的接口,二者在使用层面,有很大的相似性 二 开启线程的两种方式 方式一 from threading import Thread import time def sayhi(name): time.sleep(2) print("%s say hello" % name) if __name__ == '__main__': t = Thread(target=sayhi, args=('mik

python并发编程之多线程编程

一.threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再详细介绍 二.开启线程的两种方式 方式一: from threading import Thread import time import random def task(name): print('%s is running' %name) time.sleep(random.randint(1,3)) print('%s is end' %name)