学习笔记一伍,进程和线程

By admin in 4858.com on 2019年4月8日

壹.线程进度
进度:程序并不能够独立运维,只有将先后装载到内部存储器中,系统为它分配能源才能运作,而那种实践的顺序就叫做进程,不负有实施感念,只是程序各类财富聚合

python 三.x 学习笔记一5(多线程),python三.x

壹.线程历程
经过:程序并不可能独立运营,唯有将次第装载到内部存款和储蓄器中,系统为它分配财富才能运维,而那种实践的先后就叫做进程,不具有实践感念,只是程序各个能源汇聚

线程:线程是操作系统能够举行演算调度的不大单位。它被含有在进程之中,是进度中的实际运维单位。一条线程指的是经过中三个单1顺序的控制流,三个经过中能够并发多个线程,每条线程并行执行分裂的职务

学习笔记一伍,进程和线程。二.线程与经过的分别

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

线程共享成立它的进度的地址空间;                                         
                              进度具有和谐的地点空间。

线程能够一贯访问其进程的数据段;                                         
                              进程具有父进度的数据段的大团结的副本。

线程能够从来与其经过的其余线程通讯;                                     
                           进度必须采纳进程间通讯与手足进度展开通讯。

新线程很不难创制;                                                       
                                          新流程要求再行父流程。

线程能够对相同进度的线程实行非凡程度的支配;                             
                     进度只可以对子进程展开控制。

对主线程的变动(撤消,优先级更改等)大概会影响进程其余线程的一言一动;       
    对父进度的转移不会影响子进程。

 

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

4.线程锁
   
每个线程在要修改公共数据时,为了制止自身在还没改完的时候别人也来修改此数量,能够给那么些数据加一把锁,
那样任何线程想修改此数额时就亟须等待你改改实现并把锁释放掉后才能再拜访此数量

 

5.Semaphore(信号量)

    互斥锁
同时只同意三个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据
,比如厕全体三个坑,那最七只允许3位上厕所,前面包车型客车人只可以等内部有人出来了才能再进来。

 

6.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()

 

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

线程参考文书档案

1,进度与线程

一.如何是线程
线程是操作系统能够进行演算调度的微乎其数码相飞机地点。它被含有在进程之中,是进度中的实际运维单位。一条线程指的是经过中1个拾足顺序的控制流,二个进度中能够并发三个线程,每条线程并行执行差异的职分
一个线程是二个执行上下文,那是二个CPU的装有音信须要履行壹多级的下令。
假若你正在读1本书,你未来想休息一下,可是你期望能够回到,苏醒从您打住的岗位。实现那一点的方法之1是因此草草记下页码、行号和数量。所以你读1本书的履行上下文是那多个数字。
若是您有一个室友,她利用同1的技巧,她能够把书当你不接纳它,并连任读书,她停了下去。然后你就能够把它拿回来,恢复生机你在哪个地方。
线程在平等的秘籍工作。CPU是给你的错觉同时做四个总括。它经过花一点日子在各种总括。它能够这么做,因为它有三个为每种计算执行上下文。就如你能够与你的爱人分享1本书,很多职责能够共享CPU。
越来越多的技术水平,三个推行上下文(因而八个线程)由CPU的寄存器的值。
最终:线程分歧于流程。执行线程的上下文,而经过是一批能源与计量有关。1个进度可以有贰个或八个线程。
驳斥没有根据的话:与流程相关的财富包蕴内部存款和储蓄器页(三个历程中的全体线程都有相同的视图的内部存款和储蓄器),文件讲述符(如。、打开的套接字)和安全凭据(如。,用户的ID初叶那么些进度)。

二.怎么是经过
三个履行顺序被称作进度的实例。
各类进程提供了所需的财富来举办三个顺序。进程的虚拟地址空间,可举办代码,打开系统处理对象,一个有惊无险上下文,二个非正规的经过标识符,环境变量,优先类,最小和最大工作集大小和至少三个线程的实践。每一种流程初叶2个线程,日常被称呼主要的线程,但从它的其他线程能够创建额外的线程。

三.经过与线程的分别

  1. 线程共享创立它的经过的地方空间,进度有友好的地址空间。
  2. 线程直接待上访问的数据段进度;进程有本人的复制父进度的数据段。
  3. 线程能够一向与别的线程的通讯过程,进程必须利用进程间通讯和同胞交流进程。
  4. 新成立的线程很不难;新工艺要求复制父进度。
  5. 线程能够锻练不小的主宰线程相同的历程;流程只可以控制子进度。
  6. 主线程变更(撤消、优先级变化等)只怕会潜移默化进度的任何线程的行为;父进度的浮动不会影响子进

4.Python GIL(Global Interpreter Lock)
大局解释器锁在CPython的,或GIL,是三个互斥锁,幸免三个地点线程执行Python字节码。这把锁是必需的,首借使因为CPython的内部存款和储蓄器管理不是线程安全的。(然则,由于GIL存在,别的职能已经数见不鲜于依靠保证实施)。
首先须求通晓的一点是GIL并不是Python的表征,它是在落到实处Python解析器(CPython)时所引进的三个概念。就好比C++是1套语言(语法)标准,但是能够用分化的编写翻译器来编写翻译成可实施代码。盛名的编写翻译器例如GCC,INTEL
C++,Visual
C++等。Python也1致,同样1段代码能够由此CPython,PyPy,Psyco等不等的Python执行环境来实施。像在那之中的JPython就从未GIL。可是因为CPython是大部分环境下暗中认可的Python执行环境。所以在不少人的概念里CPython便是Python,也就想当然的把GIL归纳为Python语言的弱点。所以那边要先鲜明一点:GIL并不是Python的风味,Python完全能够不借助于GIL
参照文书档案:**

线程:线程是操作系统能够举行演算调度的十分小单位。它被含有在进度之中,是进度中的实际运作单位。一条线程指的是经过中三个纯粹顺序的控制流,三个经过中能够并发八个线程,每条线程并行执行分裂的职务

线程是操作系统能够举办演算调度的微乎其卡片飞机地点,它被含有在进程中,是进程中的实际运作单位

二、多线程

102线程类似于同时举办三个区别程序,三十二线程运营有如下优点:

  1. 接纳线程能够把占据长日子的先后中的职务放到后台去处理。

  2. 用户界面可以更进一步吸引人,那样比如用户点击了三个按钮去接触某个事件的处理,能够弹出2个进度条来显示处理的快慢

  3. 程序的运转速度只怕加快
  4. 在1些守候的职务达成上如用户输入、文件读写和互联网收发数据等,线程就比较有用了。在那种景况下大家可以释放部分爱戴的财富如内存占用等等。
  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
第1导入threading 模块,那是采用二十四线程的前提。

  • start 线程准备稳当,等待CPU调度
  • setName 为线程设置名称
  • getName 得到线程名称
  • setDaemon 设置为后台线程或前台线程(暗许)
    假要是后台线程,主线程执行进度中,后台线程也在进行,主线程执行完成后,后台线程不论成功与否,均结束
    假如是前台线程,主线程执行进度中,前台线程也在进展,主线程执行完结后,等待前台线程也实践到位后,程序甘休
  • join
    每种执行种种线程,执行达成后持续往下实施,该方式使得多线程变得肤浅
  • run 线程被cpu调度后进行Thread类对象的run方法

2.Join & Daemon

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

鉴于在实际的网络服务器中对彼此的供给,线程成为越来越首要的编程模型,因为二十多线程之间比多进度之间更易于共享数据,同时线程壹般比进程更便捷


  • 线程是操作系统能够进行演算调度的微小单位。它被含有在经过中,是经过中的实际运作单位。一条线程指的是进程中一个纯粹顺序的控制流,2个进程中国科学院并发两个线程,每条线程并行执行不相同的任务。
  • OS调度CPU的小小单位|线程:一群指令(控制流),线程是承受执行的指令集
  • all the threads in a process have the same view of the
    memory在同贰个进程里的线程是共享同一块内部存款和储蓄器空间的

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

join

一).join方法的成效是阻塞主进程(挡住,不能实施join现在的说话),专注执行二十多线程。
二).10贰线程多join的处境下,依次执行各线程的join方法,前头一个实现了才能履行后边1个。
三).无参数,则等待到该线程结束,才起来施行下二个线程的join。
肆.安装参数后,则等待该线程这么长日子就随便它了(而该线程并不曾甘休)。
不管的意味就是能够举行前边的主进度了。

例如:
1经不应用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和动用合适的时域信号机制等


线程能够直接待上访问其进程的数据段;                                         
                              过程具有父进程的数据段的自身的副本。

次第并无法独立和平运动作唯有将顺序装载到内部存款和储蓄器中,系统为他分配财富才能运作,而那种实践的次序就叫做进度。

线程锁

多少个进程下得以运转八个线程,多少个线程共享父进度的内部存储器空间,也就代表每一种线程能够访问同一份数据,此时,要是3个线程同时要修改同壹份数据那就汇合世数量修改会被不是一个进度修改
鉴于线程之间是开始展览随机调度,并且每一种线程可能只进行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
二.7上多运行一次,会意识,最终打印出来的num结果不总是0,为何每便运行的结果不一致啊?
哈,很简短,借使你有A,B四个线程,此时都 要对num 进行减壹操作,
由于三个线程是出新同时运维的,所以一个线程很有非常大可能率同时拿走了num=100以此初阶变量交给cpu去运算,当A线程去处完的结果是9玖,但那时B线程运算完的结果也是9玖,多少个线程同时CPU运算的结果再赋值给num变量后,结果就都以9九。那咋办吧?
很不难,种种线程在要修改公共数据时,为了防止本身在还没改完的时候别人也来修改此数量,能够给那些数额加一把锁,
那样任何线程想修改此数额时就非得等待你改改完结并把锁释放掉后才能再拜访此数量。
*注:不要在三.x上运营,不知为啥,3.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 )

RLock(递归锁)
简不难单就是在一个大锁中还要再包括子锁

Semaphore(信号量)

互斥锁
同时只同意五个线程更改数据,而塞马phore是同时允许一定数量的线程更改数据
,比如厕全部1个坑,那最八只允许三个人上厕所,前边的人只可以等内部有人出来了才能再进来。

event

2个风浪是一个简练的联合对象;

事件代表三个里头国旗,和线程

能够等待标志被装置,或许设置或解除标志本人。

事件= threading.Event()

、#客户端线程等待国旗能够设置

event.wait()#服务器线程能够设置或重置它

event.set()

event.clear()

若果设置了国旗,等措施不做其余事。

如果标明被清除,等待会阻塞,直到它再也成为集。

随便数量的线程大概等待相同的风云。

Python提供了伊芙nt对象用于线程间通讯,它是由线程设置的信号标志,假如实信号标志位真,则其余线程等待直到信号接触。

伊夫nt对象实现了归纳的线程通讯机制,它提供了安装功率信号,清楚实信号,等待等用于落到实处线程间的通讯。

壹 设置非时限信号

采纳伊芙nt的set()方法可以安装伊夫nt对象内部的时域信号标志为真。伊芙nt对象提供了isSet()方法来判定其里面复信号标志的景况。当使用event对象的set()方法后,isSet()方法再次回到真

二 清除非复信号

使用伊芙nt对象的clear()方法能够排除伊夫nt对象内部的确定性信号标志,即将其设为假,当使用伊芙nt的clear方法后,isSet()方法重回假

3 等待

伊夫nt对象wait的主意唯有在中间频限信号为实在时候才会快速的履行并完毕重临。当伊夫nt对象的中间时域信号标志位假时,则wait方法平昔等候到其为真时才回去。

事件处理的编写制定:全局定义了一个“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限制数量的物料能够放在队列中。插入块壹旦达到那么些尺寸,直到队列项。若是最大尺寸小于或等于零,队列大小是最为的。

劳动者消费模型

线程能够平素与其经过的任何线程通讯;                                     
                           进度必须利用过程间通讯与男生进度展开通讯。

## 程序和进程的分别在于:程序是命令的集合,它是经过的静态描述文本;进度是程序的二遍施行活动,属于动态概念。

二、多进程

案例:

#!/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('我是华丽的分隔符')

新线程很简单成立;                                                       
                                          新流程要求重新父流程。

进度是操作系统对贰个正值运行的程序的壹种浮泛。即经过是电脑,主存,IO设备的指雁为羹

注意:由于经过之间的数额要求各自全体1份,所以成立进程供给的格外大的付出。

线程可以对相同进度的线程举行相当程度的支配;                             
                     进度只好对子进度展开控制。

操作系统能够而且运行七个进程,而各类进程都就像在独占的运用硬件


  • 种种程序在内存里都分配有独立的空中,暗中同意进程间是不可能互相访问数据和操作的
  • (QQ,excel等)程序要以三个完全的方式揭露给操作系统一管理理,里面富含各样能源的调用(调用内部存款和储蓄器的治本、网络接口的调用等),对各类能源管理的成团就能够称之为进度。
  • 比如说整个QQ就足以称作一个进度
  • 进度要操作CPU(即发送指令),必须先创设1个线程;
  • 进度本身不可能履行,只是财富的集合,想要执行必须先生成操作系统实行调度运算的微乎其单反元-》线程;贰个进程要实施,必须至少存有一个线程。当创制1个进度时,会自行成立2个线程

经过数据共享

进度各自持有1份数据,暗中认可不能够共享数据
比如:

#!/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。一句话表达怎么着是线程:协程是一种用户态的轻量级线程。

协程拥有和谐的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到任什么地点方,在切回到的时候,苏醒原先封存的寄存器上下文和栈。因此:

协程能保留上叁回调用时的景观(即具备片段情状的二个一定组合),每一遍经过重入时,就也便是进入上贰遍调用的情况,换种说法:进入上一遍离开时所处逻辑流的岗位。

协程的补益:

无需线程上下文切换的开销
无需原子操作锁定及同步的开销
方便切换控制流,简化编程模型
高并发+高扩展性+低成本:一个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)

4858.com,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

对主线程的改观(打消,优先级更改等)大概会潜移默化进度其余线程的作为;       
    对父进程的改变不会影响子进程。

经过和线程的界别?

  • 线程共享创设它的历程的地方空间,进程的内部存款和储蓄器空间是独立的
  • 多少个线程直接待上访问数据经过的数目,数据时共享的;二个父进度中的几个子进度对数据的走访其实是仿制,互相之间是独自的。
  • 线程能够一直与创建它的长河的其余线程通讯;3个父进度的子进度间的通讯必须经过三个中档代理来达成
  • 新的线程简单创立;创立新历程必要对其父进程展开一回克隆
  • 线程能够对创制它的历程中的线程举行控制和操作,线程之间从未实际的专属关系;进程只可以对其子进度展开控制和操作
  • 对主线程的更改(裁撤、优先级更改等)恐怕影响进程的此外线程的一坐一起;对进度的变更不会影响子进程

!/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
是1个第贰方库,能够轻松通过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

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

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

“`

  • 此处结果为2秒多或多或少,计算时间正确,用于此现象时,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(信号量)

线程锁

  • 各类线程在要修改公共数据时,为了制止自身在还没改完的时候外人也来修改此数据,能够给这么些数目加1把锁,
    这样任何线程想修改此数量时就非得等待你改改实现并把锁释放掉后才能再拜访此数量。
  • 线程锁将线程变为串行

    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)

    互斥锁
同时只允许3个线程更改数据,而Semaphore是还要同意一定数量的线程更改数据
,比如厕全体二个坑,那最七只同意贰位上洗手间,后面包车型地铁人只好等中间有人出来了才能再进来。

RLock(递归锁)

  • 多层锁的时候使用,说白了正是在1个大锁中还要再包括子锁
    “`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)

  • 互斥锁(线程锁)
    同时只同意1个线程更改数据,而Semaphore是同时允许一定数额的线程更改数据
    ,比如厕全体三个坑,那最两只允许四位上厕所,后边的人不得不等内部有人出来了才能再进入。
  • 每释放二个锁,立时进贰个线程(例如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)
    

6.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地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有