经过和线程,学习笔记一⑤

一.线程进度
经过:程序并不能独立运维,唯有将次第装载到内存中,系统为它分配资源才能运营,而那种实践的主次就称为进度,不拥有实施感念,只是程序种种能源集合

python 3.x 学习笔记一伍(八线程),python三.x

1.线程进程
经过:程序并无法独立运营,只有将次第装载到内部存储器中,系统为它分配能源才能运营,而那种实践的主次就称为进度,不富有实践感念,只是程序各样财富集合

线程:线程是操作系统可以举办演算调度的微小单位。它被含有在进度之中,是经过中的实际运作单位。一条线程指的是进度中二个纯粹顺序的控制流,一个进度中得以并发多个线程,每条线程并行执行分裂的天职

二.线程与经过的区分

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

线程共享成立它的进度的地址空间;                                         
                              进度具有本身的地址空间。

线程能够一向访问其经过的数据段;                                         
                              进度具有父进度的数据段的自个儿的副本。

线程能够直接与其进度的其余线程通信;                                     
                           进程必须运用进程间通讯与兄弟进程展开通讯。

新线程很不难创造;                                                       
                                          新流程须求再行父流程。

线程能够对同1进度的线程举行相当程度的操纵;                             
                     进程只好对子进度展开控制。

对主线程的改动(废除,优先级更改等)恐怕会潜移默化进度其余线程的一言一动;       
    对父进度的改观不会影响子进度。

 

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

4.线程锁
   
每一种线程在要修改公共数据时,为了防止本人在还没改完的时候外人也来修改此数额,能够给这么些数量加1把锁,
那样任何线程想修改此数量时就不能够不等待你改改达成并把锁释放掉后才能再拜访此数据

 

5.Semaphore(信号量)

    互斥锁
同时只允许三个线程更改数据,而Semaphore是还要同意一定数额的线程更改数据
,比如厕全数一个坑,那最三只同意二位上洗手间,后边的人不得不等中间有人出来了才能再进入。

 

陆.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五(二1010二线程),python三.x
壹.线程进度进度:程序并无法独立运营,唯有将次第装载到内部存款和储蓄器中,系统为它分配财富才能运作,而那…

线程参考文书档案

一,进程与线程

一.什么样是线程
线程是操作系统可以举行演算调度的蝇头单位。它被含有在进度之中,是进度中的实际运作单位。一条线程指的是经过中3个纯净顺序的控制流,1个进程中得以并发四个线程,每条线程并行执行分化的职务
四个线程是1个推行上下文,这是多个CPU的保有音讯须求实践一文山会海的吩咐。
设若你正在读一本书,你以后想休息一下,但是你期望能够回到,恢复生机从您打住的岗位。实现那一点的办法之一是透过草草记下页码、行号和多少。所以您读一本书的推行上下文是那多少个数字。
一旦您有三个室友,她选择同一的技巧,她能够把书当你不应用它,并延续读书,她停了下去。然后你就能够把它拿回来,恢复你在哪儿。
线程在同一的措施工作。CPU是给你的错觉同时做八个总计。它经过花一点岁月在各种总结。它能够这么做,因为它有多少个为每一种总结执行上下文。就像你能够与你的仇敌分享壹本书,很多职责能够共享CPU。
越来越多的技术水平,2个实践上下文(因而叁个线程)由CPU的寄存器的值。
末尾:线程区别于流程。执行线程的上下文,而经过是一批能源与总括有关。1个进度能够有七个或七个线程。
弄清:与流程相关的财富包涵内存页(3个经过中的全数线程都有平等的视图的内部存款和储蓄器),文件讲述符(如。、打开的套接字)和安全凭据(如。,用户的ID初始那几个进度)。

二.什么样是进度
多个进行顺序被称之为进程的实例。
各个进程提供了所需的财富来执行一个程序。进度的虚拟地址空间,可实施代码,打开系统处理指标,三个吐鲁番上下文,一个出色的长河标识符,环境变量,优先类,最小和最大工作集大小和至少叁个线程的施行。各个流程开头1个线程,常常被喻为首要的线程,但从它的别的线程可以创立额外的线程。

三.进程与线程的差距

  1. 线程共享成立它的长河的地方空间,过程有温馨的地址空间。
  2. 线程直接访问的数据段进程;进度有投机的复制父进度的数据段。
  3. 线程能够一向与其它线程的通讯进程,进程必须选取进程间通信和同胞沟通进度。
  4. 新创制的线程很不难;新工艺要求复制父进程。
  5. 线程能够磨练相当的大的控制线程相同的长河;流程只好控制子进度。
  6. 主线程变更(撤销、优先级变化等)或然会潜移默化进度的别的线程的行事;父进度的变通不会影响子进

4.Python GIL(Global Interpreter Lock)
大局解释器锁在CPython的,或GIL,是一个互斥锁,制止三个地点线程执行Python字节码。那把锁是必不可缺的,主假设因为CPython的内部存款和储蓄器管理不是线程安全的。(不过,由于GIL存在,其余职能已经熟视无睹于依靠有限帮助实施)。
第三供给鲜明的有个别是GIL并不是Python的特性,它是在落成Python解析器(CPython)时所引入的1个定义。就好比C++是一套语言(语法)标准,不过能够用差别的编写翻译器来编写翻译成可进行代码。著名的编写翻译器例如GCC,INTEL
C++,Visual
C++等。Python也同样,同样壹段代码可以通过CPython,PyPy,Psyco等不等的Python执行环境来进行。像当中的JPython就从未有过GIL。不过因为CPython是绝超越13分之5条件下暗许的Python执行环境。所以在许四人的定义里CPython就是Python,也就想当然的把GIL总结为Python语言的弱点。所以那里要先明了一点:GIL并不是Python的特征,Python完全能够不借助于于GIL
参考文书档案:**

线程:线程是操作系统可以进行演算调度的矮小单位。它被含有在经过之中,是经过中的实际运作单位。一条线程指的是进程中三个纯粹顺序的控制流,叁个历程中得以并发五个线程,每条线程并行执行区别的天职

线程是操作系统可以举行演算调度的细卡片飞机地方,它被含有在经过中,是经过中的实际运作单位

二、多线程

四线程类似于同时实行七个分歧程序,四线程运行有如下优点:

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

  2. 用户界面可以更进一步吸引人,那样比如用户点击了三个按钮去接触有些事件的拍卖,能够弹出一个进程条来突显处理的进程

  3. 程序的运营速度大概加快
  4. 在1些守候的职责落到实处上如用户输入、文件读写和互连网收发数据等,线程就相比较有用了。在那种状态下我们能够释放部分难得的财富如内部存款和储蓄器占用等等。
  5. 线程在推行进度中与经过依然有分其他。各样独立的线程有1个程序运营的入口、顺序执行种类和次序的发话。但是线程不可能单独执行,必须依存在应用程序中,由应用程序提供三个线程执行控制。
  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根据钦命算法进行调度,分片执行命令

二.线程与经过的界别

经过和线程,学习笔记一⑤。3个经超过实际际能够由五个线程的进行单元构成。每一个线程都运作在经过的内外文中,并共享同样的代码和全局数据。

显明与艺术:

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在同三个进度里的线程是共享同壹块内部存款和储蓄器空间的

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

join

一).join方法的机能是阻塞主进度(挡住,不可能推行join未来的讲话),专注执行四线程。
二).二十三二十四线程多join的图景下,依次执行各线程的join方法,前头1个终了了才能履行后边三个。
3).无参数,则等待到该线程甘休,才起来实施下2个线程的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份数据,此时,借使一个线程同时要修改同一份数据那就会并发数量修改会被不是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
2.七上多运转两次,会发现,最终打字与印刷出来的num结果不总是0,为何老是运行的结果不1样吧?
哈,很简短,借使你有A,B四个线程,此时都 要对num 实行减一操作,
由于贰个线程是出新同时运营的,所以三个线程很有望同时拿走了num=100那几个开端变量交给cpu去运算,当A线程去处完的结果是99,但那时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 )

RLock(递归锁)
简不难单便是在二个大锁中还要再包涵子锁

Semaphore(信号量)

互斥锁
同时只同意三个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据
,比如厕全部二个坑,这最四只同意四人上厕所,后边的人只可以等中间有人出来了才能再进来。

event

贰个事件是2个简练的壹块儿对象;

事件表示3个之中华夏族民共和国旗,和线程

能够等待标志棉被服装置,只怕安装或解除标志本人。

事件= threading.Event()

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

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

event.set()

event.clear()

只要设置了国旗,等办法不做别的事。

假如标明被铲除,等待会阻塞,直到它再一次成为集。

随便数量的线程或者等待相同的事件。

Python提供了伊芙nt对象用于线程间通讯,它是由线程设置的复信号标志,借使频限信号标志位真,则别的线程等待直到实信号接触。

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

一 设置复信号

利用伊夫nt的set()方法可以设置伊夫nt对象内部的时限信号标志为真。伊芙nt对象提供了isSet()方法来判定其中间数字信号标志的景况。当使用event对象的set()方法后,isSet()方法重临真

二 清除实信号

选用Event对象的clear()方法能够去掉伊夫nt对象内部的实信号标志,即将其设为假,当使用伊夫nt的clear方法后,isSet()方法再次来到假

3 等待

伊芙nt对象wait的措施唯有在个中国国投号为真正时候才会相当的慢的推行并达成再次回到。当伊夫nt对象的个中国国际信资公司号标志位假时,则wait方法一向守候到其为真时才回去。

事件处理的编写制定:全局定义了2个“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设备的画饼充饥

小心:由于经过之间的数码须求各自拥有一份,所以创制进度要求的非常的大的花费。

线程可以对同样进度的线程举行万分程度的主宰;                             
                     进度只好对子进程展费用配。

操作系统能够而且运行多少个经过,而种种进度都接近在独占的使用硬件


  • 各种程序在内部存款和储蓄器里都分配有独立的上空,暗许进度间是无法相互走访数据和操作的
  • (QQ,excel等)程序要以3个总体的花样暴露给操作系统一管理理,里面包罗各样财富的调用(调用内部存款和储蓄器的田管、网络接口的调用等),对各个财富管理的聚合就能够叫做进度。
  • 譬如说整个QQ就足以称呼二个历程
  • 进度要操作CPU(即发送指令),必须先创设2个线程;
  • 进度自己不可能实施,只是能源的聚合,想要执行必须先生成操作系统实行调度运算的细卡片机元-》线程;三个进度要执行,必须至少存有一个线程。当创制3个经过时,会活动创立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。一句话表明哪些是线程:协程是1种用户态的轻量级线程。

协程拥有本人的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到别的地点,在切回到的时候,复苏原先保留的寄存器上下文和栈。因而:

协程能保存上1次调用时的地方(即怀有片段情况的三个一定组合),每一趟经过重入时,就约等于进入上一回调用的气象,换种说法:进入上3回离开时所处逻辑流的岗位。

协程的好处:

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

对主线程的改观(撤消,优先级更改等)可能会潜移默化进度别的线程的一言一动;       
    对父进程的改变不会影响子进度。

经过和线程的界别?

  • 线程共享创建它的经过的地点空间,进程的内部存款和储蓄器空间是独立的
  • 八个线程直接待上访问数据经过的多少,数据时共享的;三个父进度中的多少个子进度对数据的造访其实是克隆,互相之间是独自的。
  • 线程能够一向与创制它的经过的别样线程通讯;贰个父进度的子进度间的通讯必须经过贰个在这之中代理来促成
  • 新的线程不难创设;创设新历程须要对其父进程展开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()
#万1那里加入t.join()则等待每一个线程执行完结再拓展下3个线程,10二线程变成了串行
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
是3个第三方库,能够轻松通过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()当前进度活跃个数

“`

  • 此间结果为二秒多或多或少,总结时间正确,用于此情况时,join()必须在富有线程的start()之后,不然成为十二线程串行,二十八线程就无意义了

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)

    互斥锁
同时只同意多少个线程更改数据,而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是同时允许一定数额的线程更改数据
    ,比如厕全数三个坑,那最七只允许4位上厕所,前面包车型大巴人不得不等内部有人出来了才能再进入。
  • 每释放贰个锁,立即进四个线程(例如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的成效是 等待线程执行实现

继承式10二线程

  • 壹般不用

 

通过类的样式=》十二线程

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

 

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website