一.线程进程
进度:程序并不能够独立运转,唯有将顺序装载到内部存款和储蓄器中,系统为它分配能源技艺运转,而这种实行的程序就称为进度,不抱有实行感念,只是程序各个财富集结

python 三.x 学习笔记一五(三十六线程),python3.x

壹.线程历程
进程:程序并不能独立运转,唯有将顺序装载到内部存储器中,系统为它分配财富本事运作,而那种实行的主次就称为进度,不有所实行感念,只是程序各类财富集中

线程:线程是操作系统能够实行演算调整的蝇头单位。它被含有在进程之中,是进度中的实际运作单位。一条线程指的是进程中一个纯净顺序的调节流,贰个进度中得以并发多少个线程,每条线程并行奉行区别的任务

二.线程与经过的分别

线程共享内部存款和储蓄器空间,                                                     
                                         进度的内部存款和储蓄器是单独的

线程共享创造它的进程的地址空间;                                         
                              进程具备自个儿的地方空间。

线程能够直接待上访问其进程的数据段;                                         
                              进度具有父进程的数据段的温馨的别本。

线程能够一向与其经过的别样线程通讯;                                     
                           进度必须利用进度间通讯与兄弟进程展开通讯。

新线程很轻松创立;                                                       
                                          新流程须要再一次父流程。

线程能够对同一进度的线程进行拾1分程度的决定;                             
                     进度只可以对子进度展开调整。

对主线程的更换(裁撤,优先级改换等)大概会潜移默化过程其余线程的行为;       
    对父进度的改变不会影响子进程。

 

三.一条线程至少有一条线程

4.线程锁
   
每一种线程在要修改公共数据时,为了幸免自身在还没改完的时候外人也来修改此数量,能够给这一个数据加一把锁,
这样任何线程想修改此数据时就亟须等待你改改落成并把锁释放掉后技巧再拜访此数额

 

5.Semaphore(信号量)

    互斥锁
同时只同意叁个线程改造数据,而塞马phore是同时允许一定数量的线程改动数据
,比方厕全体二个坑,那最五只允许4人上厕所,前边的人只能等内部有人出来了才干再进入。

 

陆.join的法力是 等待线程施行完成

 

7.练习

信号量

__author__ = "Narwhale"

import threading,time

def run(n):
    semaphore.acquire()
    time.sleep(1)
    print('线程%s在跑!'%n)
    semaphore.release()

if __name__ == '__main__':
    semaphore = threading.BoundedSemaphore(5)      #最多5个线程同时跑
    for i in range(20):
        t = threading.Thread(target=run,args=(i,))
        t.start()

while threading.active_count() !=1:
    pass
else:
    print('所有线程跑完了!')

生产者消费者模型

__author__ = "Narwhale"
import queue,time,threading
q = queue.Queue(10)

def producer(name):
    count = 0
    while True:
        print('%s生产了包子%s'%(name,count))
        q.put('包子%s'%count)
        count += 1
        time.sleep(1)

def consumer(name):
    while True:
        print('%s取走了%s,并且吃了它。。。。。'%(name,q.get()))
        time.sleep(1)


A1 = threading.Thread(target=producer,args=('A1',))
A1.start()

B1 = threading.Thread(target=consumer,args=('B1',))
B1.start()
B2 = threading.Thread(target=consumer,args=('B2',))
B2.start()

红绿灯

__author__ = "Narwhale"

import threading,time

event = threading.Event()

def light():
    event.set()
    count = 0
    while True:
        if count >5 and count < 10:
            event.clear()
            print('\033[41;1m红灯亮了\033[0m' )
        elif count > 10:
            event.set()
            count = 0
        else:
            print('\033[42;1m绿灯亮了\033[0m')
        time.sleep(1)
        count +=1


def car(n):
    while True:
        if event.isSet():
            print('\033[34;1m%s车正在跑!\033[0m'%n)
            time.sleep(1)
        else:
            print('车停下来了')
            event.wait()

light = threading.Thread(target=light,args=( ))
light.start()
car1 = threading.Thread(target=car,args=('Tesla',))
car1.start()

 

三.x 学习笔记1五(八线程),python三.x
①.线程进度进度:程序并不可能独立运维,唯有将先后装载到内部存款和储蓄器中,系统为它分配能源才干运维,而这…

线程参照文书档案

一,进程与线程

一.如何是线程
线程是操作系统能够举办演算调整的小不点儿单位。它被含有在进程之中,是经过中的实际运作单位。一条线程指的是进程中二个10足顺序的调节流,一个进度中得以并发五个线程,每条线程并行试行不一致的天职
1个线程是二个实行上下文,那是一个CPU的保有消息需求实行一种种的下令。
一经你正在读一本书,你今后想停息一下,可是你期望能够回来,恢复生机从你结束的任务。达成那或多或少的点子之一是通过草草记下页码、行号和多少。所以您读一本书的推行上下文是那多少个数字。
假设你有二个室友,她利用一样的才具,她得以把书当你不行使它,并承袭阅读,她停了下来。然后您就能够把它拿回来,恢复你在哪儿。
线程在同样的法子行事。CPU是给您的错觉同时做多少个总括。它通过花一点日子在每一个总括。它能够这么做,因为它有2个为种种计算试行上下文。就如您能够与您的敌人分享1本书,多数任务能够共享CPU。
越来越多的技艺水平,二个实行上下文(因而3个线程)由CPU的寄存器的值。
最终:线程不一样于流程。施行线程的上下文,而经过是一批能源与计算有关。1个进度能够有2个或多个线程。
戮穿蜚言:与流程相关的财富包罗内存页(三个历程中的全体线程都有同样的视图的内部存储器),文件讲述符(如。、展开的套接字)和安全凭据(如。,用户的ID开端这些历程)。

2.怎么样是进程
1个施行顺序被喻为进程的实例。
每一个进度提供了所需的财富来实行3个程序。进程的虚拟地址空间,可施行代码,张开系统管理目的,3个乌兰察布上下文,三个奇特的进度标记符,情形变量,优先类,最小和最大工作集大小和至少二个线程的实践。每一个流程开始一个线程,日常被称为重要的线程,但从它的别的线程能够创建额外的线程。

三.历程与线程的区分

  1. 线程共享创建它的经过的地方空间,进度有友好的地方空间。
  2. 线程直接待上访问的数据段进程;进度有温馨的复制父进程的数据段。
  3. 线程能够一贯与别的线程的通讯进程,进度必须选用进程间通讯和亲生交换进度。
  4. 新成立的线程很轻便;新工艺供给复制父进度。
  5. 线程能够练习比较大的支配线程相同的过程;流程只可以调节子进度。
  6. 主线程改变(撤消、优先级变化等)大概会影响进度的别的线程的行事;父进程的调换不会潜移默化子进

4.Python GIL(Global Interpreter Lock)
全局解释器锁在CPython的,或GIL,是1个互斥锁,幸免八个地方线程实践Python字节码。那把锁是必备的,重假若因为CPython的内部存款和储蓄器管理不是线程安全的。(可是,由于GIL存在,别的职能已经熟视无睹于依附保障执行)。
先是要求显明的少数是GIL并不是Python的表征,它是在贯彻Python解析器(CPython)时所引入的1个定义。就好比C++是1套语言(语法)规范,然则能够用不一致的编写翻译器来编译成可实践代码。有名的编写翻译器比方GCC,INTEL
C++,Visual
C++等。Python也壹致,同样一段代码能够因此CPython,PyPy,Psyco等不等的Python实践景况来实行。像个中的JPython就从未GIL。但是因为CPython是超越一半遭受下暗中认可的Python实施遭逢。所以在数不胜数人的概念里CPython正是Python,也就想当然的把GIL归纳为Python语言的弱点。所以那边要先鲜明一点:GIL并不是Python的风味,Python完全可以不借助于于GIL
参考文书档案:**

线程:线程是操作系统能够实行演算调节的矮小单位。它被含有在进程之中,是经过中的实际运作单位。一条线程指的是进度中3个单一顺序的调节流,1个进度中得以并发八个线程,每条线程并行施行分裂的职责

线程是操作系统能够实行演算调解的纤维单位,它被含有在进程中,是进程中的实际运作单位

二、多线程

学习笔记1五,进度和线程。102线程类似于同时实践七个例外程序,10二线程运维有如下优点:

  1. 应用线程能够把占有长日子的顺序中的职责放到后台去管理。

  2. 用户分界面能够更进一步吸引人,那样例如用户点击了二个按键去接触某个事件的拍卖,能够弹出二个进程条来显示管理的进程

  3. 先后的运维速度也许加快
  4. 在部分等候的天职落到实处上如用户输入、文件读写和互联网收发数据等,线程就相比较有用了。在那种状态下我们得以自由部分宝贵的能源如内部存款和储蓄器占用等等。
  5. 线程在试行进程中与经过如故有分其余。每一个独立的线程有二个程序运维的入口、顺序施行连串和次序的开口。可是线程不可能独立试行,必须依存在应用程序中,由应用程序提供三个线程实施调控。
  6. 各类线程都有他本人的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运维该线程的CPU寄存器的境况。
  7. 指令指针和储藏室指针寄存器是线程上下文中七个最要害的寄存器,线程总是在经过赚取上下文中运作的,这么些地址都用于标记拥有线程的经过地址空间中的内部存款和储蓄器。
  8. 线程能够被侵夺(中断)。
  9. 在任何线程正在启动时,线程能够权且搁置(也称为睡眠) —
    那正是线程的妥胁。

1.threading模块

向来调用:
import threading
import time

def code(num): #定义每个线程要运行的函数

    print("running on number:%s" %num)

    time.sleep(3)

if __name__ == '__main__':

    t1 = threading.Thread(target=code,args=(1,)) #生成一个线程实例
    t2 = threading.Thread(target=code,args=(2,)) #生成另一个线程实例

    t1.start() #启动线程
    t2.start() #启动另一个线程

    print(t1.getName()) #获取线程名
    print(t2.getName())
或者:
#!/usr/bin/env python
#coding:utf-8
import threading
import time
class A(object):#定义每个线程要运行的函数
   def __init__(self,num):
        self.num = num
        self.run()
   def run(self):
       print('线程',self.num)
       time.sleep(1)
for i in range(10):
t = threading.Thread(target=A,args=(i,))#生成一个线程实例 target对应你要执行的函数名
t.start()#启动线程

承袭类调用:

import threading
import time
class MyThread(threading.Thread):#继承threading.Thread
    def __init__(self,num):
        threading.Thread.__init__(self)
        self.num = num
    def run(self):#定义每个线程要运行的函数

        print("我是第%s个程序" %self.num)

        time.sleep(3)#执行结束后等待三秒

if __name__ == '__main__':
    t1 = MyThread(1)
    t2 = MyThread(2)
    t1.start()
    t2.start()
或者:
import threading
import time
class MyThread(threading.Thread):#继承threading.Thread
    def __init__(self,num):
        threading.Thread.__init__(self)
        self.num = num
    def run(self):#定义每个线程要运行的函数

        print("我是第%s个程序" %self.num)

        time.sleep(3)#执行结束后等待三秒

if __name__ == '__main__':
    for i in range(10):
        t = MyThread(i)
        t.start()

上述代码创制了十个“前台”线程,然后调整器就付出了CPU,CPU依据内定算法进行调节,分片施行命令

2.线程与经过的差异

二个进度实际能够由多少个线程的实行单元构成。每一个线程都运作在进度的左右文中,并共享同样的代码和大局数据。

规定与办法:

import threading
首开端入threading 模块,那是采用四线程的前提。

  • start 线程妄想妥帖,等待CPU调节
  • setName 为线程设置名称
  • getName 得到线程名称
  • setDaemon 设置为后台线程或前台线程(默许)
    只假如后台线程,主线程推行进程中,后台线程也在开始展览,主线程试行完成后,后台线程不论成功与否,均结束
    若是是前台线程,主线程试行进度中,前台线程也在张开,主线程实行落成后,等待前台线程也实行到位后,程序结束
  • join
    各种实践种种线程,实施落成后持续往下实践,该措施使得八线程变得肤浅
  • run 线程被cpu调整后进行Thread类对象的run方法

2.Join & Daemon

线程共享内部存款和储蓄器空间,                                                     
                                         进度的内部存款和储蓄器是单独的

鉴于在事实上的互连网服务器中对互相的需求,线程成为越来越首要的编制程序模型,因为八线程之间比多进度之间更便于共享数据,同时线程一般比进度更急速


  • 线程是操作系统能够举行演算调整的小小单位。它被含有在经过中,是经过中的实际运维单位。一条线程指的是进度中三个单壹顺序的调节流,三个进度中国中国科学技术大学学并发两个线程,每条线程并行执行区别的职务。
  • OS调节CPU的微乎其微单位|线程:一批指令(调整流),线程是承担施行的指令集
  • all the threads in a process have the same view of the
    memory在同3个历程里的线程是共享同一块内部存款和储蓄器空间的

  • IO操作不占用CPU(数据读取存款和储蓄),总计操作占用CPU(一+一…)
  • python10二线程,不符合CPU密集型操作,适合IO密集型操作

join

一).join方法的功力是阻塞主进度(挡住,不或者施行join未来的话语),专注施行10二线程。
二).多线程多join的情景下,依次推行各线程的join方法,前头二个得了了技术施行前边七个。
三).无参数,则等待到该线程甘休,才起来施行下八个线程的join。
四.安装参数后,则等待该线程这么长日子就随便它了(而该线程并从未停止)。
不管的意思正是足以实施前边的主进度了。

例如:
只要不应用join

import time
import threading

def run(n):

    print('正在运行[%s]\n' % n)
    time.sleep(2)
    print('运行结束--')
def main():
    for i in range(5):
        t = threading.Thread(target=run,args=[i,])
        #time.sleep(1)
        t.start()
        t.join(1)
        print('进行中的线程名', t.getName())
#第一个执行的
m = threading.Thread(target=main,args=[])
m.start()
print("---main thread done----")
print('继续往下执行')

结果如下:

---main thread done----  #线程还没结束就执行
正在运行[0]
继续往下执行               #线程还没结束就执行

进行中的线程名 Thread-2
正在运行[1]

运行结束--
进行中的线程名 Thread-3
正在运行[2]

运行结束--
进行中的线程名 Thread-4
正在运行[3]

运行结束--
进行中的线程名 Thread-5
正在运行[4]

运行结束--
进行中的线程名 Thread-6
运行结束--

借使选用join:

import time
import threading

def run(n):

    print('正在运行[%s]\n' % n)
    time.sleep(1)
    print('运行结束--')
def main():
    for i in range(5):
        t = threading.Thread(target=run,args=[i,])
        t.start()
        t.join(1)
        print('进行中的线程名', t.getName())
#第一个执行的
m = threading.Thread(target=main,args=[])
m.start()
m.join()#开启join
print("---main thread done----") #结果是线程执行完毕之后 才执行
print('继续往下执行')              #结果是线程执行完毕之后 才执行

注:join(time)等time秒,固然time内未施行完就差别了,继续往下实行
如下:

import time
import threading

def run(n):

    print('正在运行[%s]\n' % n)
    time.sleep(1)
    print('运行结束--')
def main():
    for i in range(5):
        t = threading.Thread(target=run,args=[i,])
        #time.sleep(1)
        t.start()
        t.join(1)
        print('进行中的线程名', t.getName())
#第一个执行的
m = threading.Thread(target=main,args=[])
m.start()
m.join(timeout=2) #设置时间
print("---main thread done----")
print('继续往下执行')

结果:

正在运行[0]

进行中的线程名 Thread-2
运行结束--  
正在运行[1]

运行结束--
进行中的线程名 Thread-3
---main thread done----  #执行了
继续往下执行               #执行了
正在运行[2]

运行结束--
进行中的线程名 Thread-4
正在运行[3]

运行结束--
进行中的线程名 Thread-5
正在运行[4]

运行结束--
进行中的线程名 Thread-6

线程共享成立它的进度的地方空间;                                         
                              进度具备自身的地方空间。

进程

daemon

有些线程做后台职分,比方发送keepalive包,或进行垃圾搜聚周期,等等。这几个只是有用的主程序运转时,它能够杀死他们假如其余,非守护线程退出。
从未守护程序线程,你要追踪他们,和告知她们退出,您的主次能够完全脱离。通过安装它们当做医生和医护人员进度线程,你能够让她们运维和忘记他们,当程序退出时,任何守护程序线程自动被杀。

import time
import threading

def run(n):

    print('正在运行[%s]\n' % n)
    time.sleep(1)
    print('运行结束--')
def main():
    for i in range(5):
        t = threading.Thread(target=run,args=[i,])
        time.sleep(1)
        t.start()
        t.join(1)
        print('进行中的线程名', t.getName())
#第一个执行的
m = threading.Thread(target=main,args=[])
m.setDaemon(True)#将主线程设置为Daemon线程,它退出时,其它子线程会同时退出,不管是否执行完任务
m.start()

print("---main thread done----")
print('继续往下执行')

留意:守护程序线程突然停在闭馆。他们的能源(如展开的公文、数据库事务,等等)或许不会平常发表。假如你想让您的线程甘休优雅,让他俩non-daemonic和行使相当的能量信号机制等


线程可以直接待上访问其经过的数据段;                                         
                              进度具备父进度的数据段的和谐的副本。

次第并不能够独立和平运动作只有将顺序装载到内存中,系统为他分配财富技艺运维,而那种实施的程序就叫做进程。

线程锁

一个进程下得以运转多个线程,四个线程共享父进度的内部存款和储蓄器空间,也就意味着每一个线程能够访问同壹份数据,此时,倘诺1个线程同时要修改同1份数据那就相会世数量修改会被不是1个经过修改
出于线程之间是进行随机调治,并且各类线程恐怕只举行n条施行之后,CPU接着试行其它线程。所以,或然出现如下难题:

import time
import threading

def addNum(ip):
    global num #在每个线程中都获取这个全局变量
    print('--get num:',num,'线程数',ip )
    time.sleep(1)
    num  +=1 #对此公共变量进行-1操作
    num_list.append(num)

num = 0  #设定一个共享变量
thread_list = []
num_list =[]
for i in range(10):
    t = threading.Thread(target=addNum,args=(i,))
    t.start()
    thread_list.append(t)

for t in thread_list: #等待所有线程执行完毕
    t.join()

print('final num:', num )
print(num_list)

结果:

--get num: 0 线程数 0
--get num: 0 线程数 1
--get num: 0 线程数 2
--get num: 0 线程数 3
--get num: 0 线程数 4
--get num: 0 线程数 5
--get num: 0 线程数 6
--get num: 0 线程数 7
--get num: 0 线程数 8
--get num: 0 线程数 9
final num: 10
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

常常来讲,那几个num结果应当是0, 但在python
二.柒上多运转一回,会意识,最终打字与印刷出来的num结果不总是0,为啥每一次运营的结果不等同吗?
哈,很简短,假使你有A,B四个线程,此时都 要对num 进行减1操作,
由于叁个线程是出现同时运营的,所以1个线程很有希望还要拿走了num=十0这么些开端变量交给cpu去运算,当A线程去处完的结果是9玖,但那时B线程运算完的结果也是9九,两个线程同时CPU运算的结果再赋值给num变量后,结果就都以9九。那咋办呢?
很简短,种种线程在要修改公共数据时,为了制止自身在还没改完的时候外人也来修改此数量,能够给这些数量加壹把锁,
那样任何线程想修改此数据时就必须等待你改改达成并把锁释放掉后手艺再拜访此数额。
*注:不要在三.x上运行,不知缘何,三.x上的结果一而再不错的,或者是机关加了锁

累加锁之后

import time   
import threading

def addNum():
    global num #在每个线程中都获取这个全局变量
    print('--get num:',num )
    time.sleep(1)
    lock.acquire() #修改数据前加锁
    num  -=1 #对此公共变量进行-1操作
    lock.release() #修改后释放
num = 100  #设定一个共享变量
thread_list = []
lock = threading.Lock() #生成全局锁
for i in range(100):
    t = threading.Thread(target=addNum)
    t.start()
    thread_list.append(t)

for t in thread_list: #等待所有线程执行完毕
    t.join()

print('final num:', num )

金沙注册送58,RLock(递归锁)
简言之就是在2个大锁中还要再包蕴子锁

Semaphore(信号量)

互斥锁
同时只同意二个线程更换数据,而Semaphore是同时允许一定数量的线程改动数据
,比方厕全体3个坑,那最四只同意四人上厕所,后边的人只可以等中间有人出来了本领再进来。

event

一个事变是一个简易的一同对象;

事件表示二当中间国旗,和线程

能够等待标记被安装,或许设置或消除标识自身。

事件= threading.Event()

、#客户端线程等待国旗能够安装

event.wait()#服务器线程能够安装或重新恢复设置它

event.set()

event.clear()

假如设置了国旗,等措施不做任何事。

假定标明被免去,等待会阻塞,直到它再次成为集。

轻松数量的线程恐怕等待同样的轩然大波。

Python提供了伊夫nt对象用于线程间通讯,它是由线程设置的能量信号标记,借使确定性信号标识位真,则此外线程等待直到频限信号接触。

伊芙nt对象落成了简便易行的线程通讯机制,它提供了设置复信号,清楚复信号,等待等用于落到实处线程间的通讯。

壹 设置时域信号

利用伊芙nt的set()方法可以设置伊夫nt对象内部的信号标记为真。伊芙nt对象提供了isSet()方法来判别其中间复信号标识的气象。当使用event对象的set()方法后,isSet()方法再次来到真

2 清除实信号

行使伊夫nt对象的clear()方法能够撤销伊夫nt对象内部的实信号标记,就要其设为假,当使用伊夫nt的clear方法后,isSet()方法重回假

3 等待

伊夫nt对象wait的艺术唯有在内部时限信号为真正时候才会神速的进行并形成重返。当伊芙nt对象的内部模拟信号标识位假时,则wait方法一贯等候到其为真时才再次来到。

事件处理的建制:全局定义了1个“Flag”,假使“Flag”值为
False,那么当程序执行 event.wait
方法时就会阻塞,假诺“Flag”值为True,那么event.wait 方法时便不再阻塞。

  • clear:将“Flag”设置为False
  • set:将“Flag”设置为True

案例:

#!/usr/bin/env python
#codfing:utf-8
#__author__ = 'yaoyao'
import threading
def do(event):
    print ('最先执行')
    event.wait()
    print ('最后执行')
event_obj = threading.Event()
for i in range(10):
    t = threading.Thread(target=do, args=(event_obj,))
    t.start()
print ('开始等待')
event_obj.clear()
inp = input('输入true:')
if inp == 'true':
    event_obj.set()

queque队列:
队列是专程有用在线程编制程序时务必在多少个线程之间交流安全音信。

class queue.Queue(maxsize=0) #先入先出
class queue.LifoQueue(maxsize=0) #last in fisrt out
class queue.PriorityQueue(maxsize=0) #仓库储存数据时可安装优先级的连串

构造函数为一个优先队列。最大尺寸是整数集upperbound限制数量的货品能够献身队列中。插入块1旦达到规定的规范那几个尺寸,直到队列项。假诺最大尺寸小于或等于零,队列大小是无比的。

劳动者消费模型

线程能够一贯与其进度的别的线程通讯;                                     
                           进程必须运用进程间通讯与兄弟进度张开通讯。

## 程序和进程的分别在于:程序是命令的成团,它是经过的静态描述文本;进程是程序的贰遍实践活动,属于动态概念。

二、多进程

案例:

#!/usr/bin/env python
#codfing:utf-8
from multiprocessing import Process
import threading
import time

def foo(i):
    print ('开始',i)
if __name__ == "__main__":
    for i in range(10):
        p = Process(target=foo,args=(i,))
        p.start()
        print('我是华丽的分隔符')

新线程很轻松创设;                                                       
                                          新流程供给再一次父流程。

进度是操作系统对1个正在运转的主次的壹种浮泛。即经过是Computer,主存,IO设备的虚幻

专注:由于经过之间的数目须要各自有着一份,所以创设进程要求的要命大的支付。

线程能够对一样进度的线程举行分外程度的决定;                             
                     进度只好对子进程张开调节。

操作系统可以同时运转两个经过,而各种进度都接近在独占的施用硬件


  • 各种程序在内部存款和储蓄器里都分配有单独的长空,暗中同意进度间是不能够相互走访数据和操作的
  • (QQ,excel等)程序要以二个1体化的款型揭破给操作系统一管理理,里面富含各样财富的调用(调用内部存款和储蓄器的军管、网络接口的调用等),对各个能源管理的聚合就能够称作进度。
  • 比如整个QQ就足以称作二个历程
  • 进度要操作CPU(即发送指令),必须先创立多少个线程;
  • 进程自身不可能实施,只是财富的聚焦,想要实践必须先生成操作系统进行调治运算的微乎其单反元-》线程;3个经过要进行,必须至少存有二个线程。当创造三个历程时,会活动成立二个线程

经过数据共享

进度各自全数一份数据,私下认可无法共享数据
比如:

#!/usr/bin/env python
#codfing:utf-8
#__author__ = 'yaoyao'
from multiprocessing import Process
li = []

def foo(i):
    li.append(i)
    print ('进程里的列表是',li)
if __name__ == '__main__':
    for i in range(10):
        p = Process(target=foo,args=(i,))
        p.start()
print ('打开列表 是空的',li)

来得如下:

打开列表 是空的 []
进程里的列表是 [0]
打开列表 是空的 []
进程里的列表是 [2]
打开列表 是空的 []
进程里的列表是 [3]
打开列表 是空的 []
进程里的列表是 [1]
打开列表 是空的 []
进程里的列表是 [5]
打开列表 是空的 []
进程里的列表是 [4]
打开列表 是空的 []
打开列表 是空的 []
进程里的列表是 [6]
打开列表 是空的 []
进程里的列表是 [7]
打开列表 是空的 []
进程里的列表是 [8]
打开列表 是空的 []
进程里的列表是 [9]

共享数据三种艺术:

  1. Array

    !/usr/bin/env python

    codfing:utf-8

    author = ‘yaoyao’

    from multiprocessing import Process,Array
    temp = Array(‘i’, [11,22,33,44])
    def Foo(i):
    temp[i] = 100+i
    for item in temp:
    print (i,’—–>’,item)

    if name == “main“:
    for i in range(1):
    p = Process(target=Foo,args=(i,))
    p.start()
    2.manage.dict()

协程

协程,又称微线程,纤程。英文名Coroutine。一句话表明什么是线程:协程是一种用户态的轻量级线程。

协程具备和谐的寄存器上下文和栈。协程调治切换时,将寄存器上下文和栈保存到其余地点,在切回到的时候,复苏原先保留的寄存器上下文和栈。因而:

协程能保留上一次调用时的景色(即全体片段情状的二个一定组合),每一趟经过重入时,就一定于进入上2遍调用的意况,换种说法:进入上一回离开时所处逻辑流的职位。

协程的便宜:

无需线程上下文切换的开销
无需原子操作锁定及同步的开销
方便切换控制流,简化编程模型
高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。

缺点:

无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序

应用yield落成协程操作例子    

import time
import queue
def consumer(name):
print(“—>starting eating baozi…”)
while True:
new_baozi = yield
print(“[%s] is eating baozi %s” % (name,new_baozi))
#time.sleep(1)

def producer():

r = con.__next__()
r = con2.__next__()
n = 0
while n < 5:
    n +=1
    con.send(n)
    con2.send(n)
    print("\033[32;1m[producer]\033[0m is making baozi %s" %n )

if name == ‘main‘:
con = consumer(“c1”)
con2 = consumer(“c2”)
p = producer()
Greenlet

对主线程的转移(撤废,优先级更动等)或许会影响进程其余线程的行事;       
    对父进程的改造不会影响子过程。

进程和线程的分别?

  • 线程共享制造它的长河的地方空间,进度的内存空间是独立的
  • 多个线程直接待上访问数据经过的数额,数据时共享的;贰个父进度中的多少个子进度对数据的拜访其实是仿制,相互之间是独自的。
  • 线程能够直接与创设它的进度的别样线程通讯;一个父进度的子进度间的通信必须经过贰其中间代理来得以完成
  • 新的线程轻巧创设;创立新进程须要对其父进度展开1次克隆
  • 线程能够对创立它的经过中的线程实行支配和操作,线程之间未有实际的依靠关系;进度只好对其子进度展费用配和操作
  • 对主线程的变动(撤除、优先级更换等)可能影响进程的其余线程的一言一行;对进度的转移不会影响子进度

!/usr/bin/env python

 

二十四线程并发的例证

import threading,time

def run(n)
    print("task",n)
    time.sleep(2)

t1 = threading.Thread(target=run,args=("t1",))#target=此线程要执行的代码块(函数);args=参数(不定个数参数,只有一个参数也需要加`,`,这里是元组形式)
t2 = threading.Thread(target=run,args=("t2",))
t1.start()
t2.start()
  • 开发银行多少个线程
    “`python
    import threading,time

def run(n)
print(“task”,n)
time.sleep(2)

start_time = time.time()
for i to range(50)
t = threading.Thread(target=run,args=(“t%s” %i ,))
t.start()

print(‘const’,time.time()-start_time)
“`

  • 此间计算的实行时间比二秒小繁多,因为主线程和由它运营的子线程是并行的

  • join()等候线程试行完结再持续也正是wait
    “`python
    import threading
    import time

def run(n):
print(‘task:’,n)
time.sleep(2)

start_time = time.time()
thread_list = []
for i in range(50):
t = threading.Thread(target=run,args=(i,))
t.start()
#若果那里进入t.join()则等待每一种线程实行达成再进行下一个线程,十2线程形成了串行
thread_list.append(t)

for t in thread_list:
t.join()#在线程运行后(start),加入join,等待全数创立的线程执行完成,再实践主线程

print(‘cont:’,time.time()-start_time)
print(threading.current_thread(),threading.active_count())

– coding:utf-8 –

from greenlet import greenlet

def test1():
print 12
gr2.switch()
print 34
gr2.switch()

def test2():
print 56
gr1.switch()
print 78

gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()

  
Gevent

Gevent
是三个第叁方库,能够轻易通过gevent完结产出同步或异步编制程序,在gevent中用到的最首要格局是格林let,
它是以C扩充模块方式接入Python的轻量级协程。
格林let全体周转在主程序操作系统进程的个中,但它们被同盟式地调治。

import gevent

def foo():
print(‘Running in foo’)
gevent.sleep(0)
print(‘Explicit context switch to foo again’)

def bar():
print(‘Explicit context to bar’)
gevent.sleep(0)
print(‘Implicit context switch back to bar’)

gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),])

输出:

Running in foo
Explicit context to bar
Explicit context switch to foo again
Implicit context switch back to bar

三.一条经过至少有一条线程

threading.current_thread()突显当前历程,threading.active_count()当前经过活跃个数

“`

  • 那里结果为二秒多或多或少,总结时间精确,用于此场景时,join()必须在享有线程的start()之后,不然成为10二线程串行,拾二线程就无意义了

4.线程锁
   
每种线程在要修改公共数据时,为了防止自个儿在还没改完的时候外人也来修改此数据,能够给这几个数据加一把锁,
那样任何线程想修改此数额时就必须等待你改改完结并把锁释放掉后工夫再拜访此数量

照看线程

  • 不加jion()时,主线程和子线程是并行的,线程之间是并行关系;加了join(),加了join()的线程实践实现才会继续别的线程
  • 设为【守护线程】,主线程不等待子线程实践落成,直接实行;程序会等主线程施行实现,但不会等待守护线程
    “`python
    import threading
    import time

def run(n):
print(‘task:’,n)
time.sleep(2)

start_time = time.time()
thread_list = []
for i in range(50):
t = threading.Thread(target=run,args=(i,))
t.t.setDaemon(True)#安装为守护线程,必须在start之前
#守护=》仆人,守护主人(主进度/线程),主人down了,守护的佣世间接截至
t.start()
thread_list.append(t)
print(‘cont:’,time.time()-start_time)

 

主线程不是照拂线程(也不可设置为护理线程),不等待子线程(设置为打点线程)等待二秒的小运,直接实践最终一句print()

“`

5.Semaphore(信号量)

线程锁

  • 各种线程在要修改公共数据时,为了幸免自个儿在还没改完的时候别人也来修改此数额,能够给那么些数额加一把锁,
    那样任何线程想修改此数量时就亟须等待你改改落成并把锁释放掉后本领再拜访此数据。
  • 线程锁将线程变为串行

    def run(n):

    lock.acquire()#创建锁
    global num
    num +=1
    lock.relsase#释放锁
    

    lock = threading.Lock()#实例化锁
    for i in range(50):

    t = threading.Thread(target=run,args=(i,))
    t.start()
    

    print(‘num:’,num)

    互斥锁
同时只允许2个线程更动数据,而Semaphore是还要同意一定数额的线程退换数据
,比如厕全部三个坑,那最多只同意四位上洗手间,前边的人只可以等中间有人出来了技能再进入。

RLock(递归锁)

  • 多层锁的时候利用,说白了正是在二个大锁中还要再包括子锁
    “`python
    import threading,time

def run1():
print(“grab the first part data”)
lock.acquire()
global num
num +=1
lock.release()
return num
def run2():
print(“grab the second part data”)
lock.acquire()
global num2
num2+=1
lock.release()
return num2
def run3():
lock.acquire()
res = run1()
print(‘——–between run1 and run2—–‘)
res2 = run2()
lock.release()
print(res,res2)

if name == ‘main‘:

num,num2 = 0,0
lock = threading.RLock()
for i in range(10):
    t = threading.Thread(target=run3)
    t.start()

while threading.active_count() != 1:
print(threading.active_count())
else:
print(‘—-all threads done—‘)
print(num,num2)
“`

 

信号量(Semaphore)

  • 互斥锁(线程锁)
    同时只同意叁个线程更动数据,而Semaphore是同时允许一定数量的线程更动数据
    ,举个例子厕全体三个坑,那最七只允许三人上厕所,后边的人只能等内部有人出来了本领再进入。
  • 每释放二个锁,立时进3个线程(举个例子socket_server中的并发数限制)

    import threading,time

    def run(n):

    semaphore.acquire()
    time.sleep(1)
    print("run the thread: %s\n" %n)
    semaphore.release()
    

    if name == ‘main‘:

    num= 0
    semaphore  = threading.BoundedSemaphore(5) #最多允许5个线程同时运行
    for i in range(20):
        t = threading.Thread(target=run,args=(i,))
        t.start()
    

    while threading.active_count() != 1:

    pass #print threading.active_count()
    

    else:

    print('----all threads done---')
    print(num)
    

陆.join的作用是 等待线程推行实现

承接式十二线程

  • 相似不用

 

透过类的样式=》四线程

import threading,time

class MyThread(threading.Thread)
    def __inin__(self,n)
        super(MyThread,self).__init__(n)
        self.n = n

    def run(self)#这里方法名必须为run
        print("running task",self.n)
        time.sleep(2)

t1 = MyThread(1)
t2 = MyThread(2)
t1.start()
t2.start()

7.练习

信号量

__author__ = "Narwhale"

import threading,time

def run(n):
    semaphore.acquire()
    time.sleep(1)
    print('线程%s在跑!'%n)
    semaphore.release()

if __name__ == '__main__':
    semaphore = threading.BoundedSemaphore(5)      #最多5个线程同时跑
    for i in range(20):
        t = threading.Thread(target=run,args=(i,))
        t.start()

while threading.active_count() !=1:
    pass
else:
    print('所有线程跑完了!')

劳动者消费者模型

__author__ = "Narwhale"
import queue,time,threading
q = queue.Queue(10)

def producer(name):
    count = 0
    while True:
        print('%s生产了包子%s'%(name,count))
        q.put('包子%s'%count)
        count += 1
        time.sleep(1)

def consumer(name):
    while True:
        print('%s取走了%s,并且吃了它。。。。。'%(name,q.get()))
        time.sleep(1)


A1 = threading.Thread(target=producer,args=('A1',))
A1.start()

B1 = threading.Thread(target=consumer,args=('B1',))
B1.start()
B2 = threading.Thread(target=consumer,args=('B2',))
B2.start()

红绿灯

__author__ = "Narwhale"

import threading,time

event = threading.Event()

def light():
    event.set()
    count = 0
    while True:
        if count >5 and count < 10:
            event.clear()
            print('\033[41;1m红灯亮了\033[0m' )
        elif count > 10:
            event.set()
            count = 0
        else:
            print('\033[42;1m绿灯亮了\033[0m')
        time.sleep(1)
        count +=1


def car(n):
    while True:
        if event.isSet():
            print('\033[34;1m%s车正在跑!\033[0m'%n)
            time.sleep(1)
        else:
            print('车停下来了')
            event.wait()

light = threading.Thread(target=light,args=( ))
light.start()
car1 = threading.Thread(target=car,args=('Tesla',))
car1.start()

 

相关文章

网站地图xml地图