威尼斯人线上娱乐

学习笔记一5,进度和线程

27 4月 , 2019  

一.线程历程
进程:程序并不可能独立运营,只有将先后装载到内存中,系统为它分配能源才具运作,而那种实践的顺序就称为进度,不享有施行感念,只是程序种种财富聚焦

python 叁.x 学习笔记一伍(拾2线程),python三.x

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

线程:线程是操作系统能够实行演算调节的细卡片飞机地方。它被含有在经过之中,是经过中的实际运营单位。一条线程指的是经过中一个单纯顺序的调节流,八个经过中能够并发多少个线程,每条线程并行试行分化的职责

二.线程与经过的界别

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

线程共享成立它的进度的地址空间;                                         
                              进度具备自个儿的地点空间。

线程可以直接访问其进度的数据段;                                         
                              进度具备父进度的数据段的和睦的别本。

线程能够直接与其进程的其余线程通讯;                                     
                           进度必须选用进程间通讯与手足进度张开通讯。

新线程很轻易创立;                                                       
                                          新流程供给再一次父流程。

线程可以对一样进度的线程举行非凡程度的支配;                             
                     进度只好对子进度张开调控。

对主线程的改造(撤消,优先级改换等)大概会潜移默化进度其余线程的行事;       
    对父进度的转移不会影响子进度。

 

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

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

 

5.Semaphore(信号量)

    互斥锁
同时只同意三个线程退换数据,而Semaphore是同时允许一定数额的线程改动数据
,比方厕全部三个坑,那最七只允许三位上厕所,前面包车型地铁人只可以等内部有人出来了本领再进入。

 

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

 

三.x 学习笔记一5(拾2线程),python叁.x
一.线程进度进度:程序并不能够独立运行,唯有将先后装载到内部存款和储蓄器中,系统为它分配财富才具运转,而那…

线程参考文书档案

一,进度与线程

1.什么样是线程
线程是操作系统能够进行演算调整的细单反位。它被含有在经过之中,是经过中的实际运转单位。一条线程指的是进程中3个单纯顺序的调整流,叁个历程中得以并发三个线程,每条线程并行执行差别的任务
1个线程是三个实行上下文,那是3个CPU的富有新闻供给实施一名目许多的一声令下。
万1你正在读壹本书,你今后想停歇一下,可是你希望能够回到,复苏从您打住的地方。完结这一点的法子之壹是透过草草记下页码、行号和数目。所以您读一本书的实行上下文是这四个数字。
假诺您有叁个室友,她运用同样的才具,她得以把书当您不接纳它,并持续阅读,她停了下去。然后你就足以把它拿回去,恢复生机你在何地。
线程在一样的措实施事。CPU是给您的错觉同时做五个总括。它通过花一点年华在每一种计算。它能够那样做,因为它有一个为种种总结实施上下文。就像您能够与您的情侣分享一本书,许多职分能够共享CPU。
更多的才干水平,三个实行上下文(因而3个线程)由CPU的寄存器的值。
最后:线程差别于流程。实施线程的上下文,而经过是一堆财富与总计有关。一个进度能够有二个或三个线程。
澄清:与流程相关的财富包含内部存款和储蓄器页(二个进度中的全数线程都有一样的视图的内部存款和储蓄器),文件讲述符(如。、张开的套接字)和巴中凭据(如。,用户的ID伊始那些进程)。

二.怎么是进程
三个举行顺序被称作进程的实例。
种种进度提供了所需的能源来实践1个程序。进度的虚拟地址空间,可试行代码,张开系统管理目的,1个吴忠上下文,二个万分的进度标志符,境遇变量,优先类,最小和最大专门的学问集大小和至少一个线程的进行。每一种流程早先一个线程,平时被称之为首要的线程,但从它的别的线程可以创立额外的线程。

三.历程与线程的区分

  1. 线程共享创立它的经过的地点空间,进度有和好的地方空间。
  2. 线程直接待上访问的数据段进度;过程有谈得来的复制父进度的数据段。
  3. 线程能够从来与任何线程的通讯进程,进度必须使用进程间通讯和亲生沟通进度。
  4. 新创设的线程很轻便;新工艺须要复制父进度。
  5. 线程能够操练相当的大的调节线程一样的长河;流程只好调控子进程。
  6. 主线程更动(撤废、优先级变化等)大概会潜移默化进度的任何线程的行为;父进程的变型不会影响子进

学习笔记一5,进度和线程。4.Python GIL(Global Interpreter Lock)
大局解释器锁在CPython的,或GIL,是二个互斥锁,防止七个地点线程实行Python字节码。那把锁是必需的,主借使因为CPython的内部存款和储蓄器管理不是线程安全的。(可是,由于GIL存在,其余职能已经习认为常于依赖保障实践)。
先是须求肯定的有个别是GIL并不是Python的天性,它是在实现Python解析器(CPython)时所引进的3个概念。就好比C++是1套语言(语法)规范,不过足以用不相同的编写翻译器来编译成可实行代码。出名的编写翻译器比方GCC,INTEL
C++,Visual
C++等。Python也同样,一样壹段代码能够经过CPython,PyPy,Psyco等区别的Python奉行意况来试行。像当中的JPython就从未GIL。不过因为CPython是诸多境况下暗中同意的Python实行情况。所以在无数人的概念里CPython便是Python,也就想当然的把GIL归纳为Python语言的短处。所以那边要先显明一点:GIL并不是Python的特征,Python完全能够不依赖于GIL
参照文书档案:**

线程:线程是操作系统能够实行演算调解的小不点儿单位。它被含有在经过之中,是经过中的实际运转单位。一条线程指的是经过中多个10足顺序的调节流,1个进程中能够并发三个线程,每条线程并行实施不一致的职务

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

二、多线程

八线程类似于同时推行三个例外程序,二十四线程运维有如下优点:

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

  2. 用户分界面能够进一步吸引人,那样例如用户点击了一个开关去接触有些事件的拍卖,能够弹出三个进度条来展现管理的快慢

  3. 次第的运营速度可能加快
  4. 在有个别守候的职责实现上如用户输入、文件读写和互联网收发数据等,线程就相比较有用了。在那种情状下大家能够自由部分尊贵的财富如内部存储器占用等等。
  5. 线程在推行进度中与经过依旧有分别的。种种独立的线程有二个程序运营的输入、顺序实行连串和程序的说话。不过线程不可以单独执行,必须依存在应用程序中,由应用程序提供多个线程实行调控。
  6. 每一种线程都有她和睦的1组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 模块,那是利用10二线程的前提。

  • start 线程图谋伏贴,等待CPU调治
  • setName 为线程设置名称
  • getName 获得线程名称
  • setDaemon 设置为后台线程或前台线程(暗许)
    只假使后台线程,主线程推行进度中,后台线程也在进行,主线程实行完结后,后台线程不论成功与否,均甘休
    若是是前台线程,主线程推行进度中,前台线程也在拓展,主线程实践落成后,等待前台线程也举行到位后,程序截至
  • join
    各个施行种种线程,推行完毕后持续往下进行,该措施使得二十四线程变得肤浅
  • run 线程被cpu调解后实行Thread类对象的run方法

2.Join & Daemon

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

由于在实际上的互联网服务器中对互相的需要,线程成为特别主要的编制程序模型,因为拾二线程之间比多进程之间更便于共享数据,同时线程一般比进度更火速


  • 线程是操作系统能够实行演算调解的微小单位。它被含有在进度中,是经过中的实际运作单位。一条线程指的是进程中3个纯粹顺序的调整流,二个进度中国中国科学技术大学学并发两个线程,每条线程并行施行不一致的天职。
  • OS调节CPU的小小单位|线程:一群指令(调整流),线程是肩负推行的指令集
  • all the threads in a process have the same view of the
    memory在同3个历程里的线程是共享同1块内部存款和储蓄器空间的

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

join

一).join方法的功能是阻塞主进程(挡住,不能够实践join今后的话语),专注推行多线程。
贰).多线程多join的情况下,依次施行各线程的join方法,前头2个截至了本领举行后边二个。
三).无参数,则等待到该线程甘休,才初始执行下三个线程的join。
4.装置参数后,则等待该线程这么长日子就不管它了(而该线程并未甘休)。
不管的情致就是能够举行前面包车型客车主进度了。

例如:
假设不接纳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
2.七上多运转三遍,会发掘,最后打字与印刷出来的num结果不总是0,为啥老是运营的结果不壹致啊?
哈,很简短,假使你有A,B五个线程,此时都 要对num 进行减一操作,
由于1个线程是出现同时运营的,所以2个线程很有相当的大可能率同时拿走了num=十0那些开始变量交给cpu去运算,当A线程去处完的结果是9九,但此时B线程运算完的结果也是9玖,多个线程同时CPU运算的结果再赋值给num变量后,结果就都是9九。这怎么办吧?
很简短,每种线程在要修改公共数据时,为了幸免自身在还没改完的时候外人也来修改此数额,可以给这些数量加一把锁,
那样任何线程想修改此数量时就务须等待你改改完成并把锁释放掉后技术再拜访此数据。
*注:不要在3.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

一个风波是三个简便的一块儿对象;

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

能够等待标识被安装,或然安装或免除标记自己。

事件= threading.Event()

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

event.wait()#服务器线程能够设置或重新载入参数它

event.set()

event.clear()

倘使设置了国旗,等措施不做其余事。

设若标明被化解,等待会阻塞,直到它再也成为集。

自便数量的线程可能等待一样的事件。

Python提供了伊芙nt对象用于线程间通讯,它是由线程设置的实信号标识,要是时限信号标识位真,则别的线程等待直到非确定性信号接触。

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

一 设置确定性信号

利用伊芙nt的set()方法能够设置伊芙nt对象内部的实信号标记为真。伊芙nt对象提供了isSet()方法来推断其里面功率信号标记的图景。当使用event对象的set()方法后,isSet()方法再次回到真

二 清除时域信号

运用伊夫nt对象的clear()方法能够清除Event对象内部的非确定性信号标识,将要其设为假,当使用伊夫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限制数量的货色能够献身队列中。插入块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('我是华丽的分隔符')

新线程很轻松创设;                                                       
                                          新流程需求重新父流程。

经过是操作系统对三个正值周转的主次的一种浮泛。即经过是Computer,主存,IO设备的悬空

注意:由于经过之间的多寡必要各自全数壹份,所以创制进程供给的百般大的支出。

线程能够对同一进度的线程举行特出程度的支配;                             
                     进度只好对子进度展开销配。

操作系统能够同时运营八个经过,而各类进度都类似在独占的选用硬件


  • 各样程序在内存里都分配有单独的上空,暗中认可进程间是不能够相互访问数据和操作的
  • (QQ,excel等)程序要以1个完好无缺的款型揭露给操作系统管理,里面含有各样能源的调用(调用内部存款和储蓄器的田间管理、网络接口的调用等),对各类能源管理的集聚就足以称作进度。
  • 举个例子整个QQ就能够称作3个经过
  • 进度要操作CPU(即发送指令),必须先创制三个线程;
  • 进度本人不能推行,只是财富的集合,想要实行必须先生成操作系统举行调解运算的细微单元-》线程;三个进程要实行,必须至少存有1个线程。当创造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。一句话表明如何是线程:协程是壹种用户态的轻量级线程。

协程具备自个儿的寄存器上下文和栈。协程调解切换时,将寄存器上下文和栈保存到其余地点,在切回到的时候,恢复生机原先保留的寄存器上下文和栈。因而:

协程能保留上一回调用时的动静(即全数片段境况的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

对主线程的变动(裁撤,优先级退换等)恐怕会影响进度别的线程的作为;       
    对父进度的转移不会影响子进程。

经过和线程的分裂?

  • 线程共享创制它的历程的地点空间,进度的内存空间是单独的
  • 多少个线程直接访问数据经过的多少,数据时共享的;多个父进度中的七个子进度对数码的访问其实是仿造,相互之间是单身的。
  • 线程能够直接与成立它的进度的其他线程通讯;一个父进度的子进度间的通讯必须经过二个中间代理来贯彻
  • 新的线程轻便创制;创制新历程要求对其父进度张开一回克隆
  • 线程能够对创造它的经过中的线程实行支配和操作,线程之间未有实际的依靠关系;进度只好对其子进度张开支配和操作
  • 对主线程的改换(撤废、优先级退换等)恐怕影响进度的任何线程的一颦一笑;对进度的改观不会影响子进程

!/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)
“`

  • 这边总计的实行时间比2秒小繁多,因为主线程和由它运营的子线程是并行的

  • 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()则等待每种线程试行达成再实行下三个线程,多线程形成了串行
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

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

threading.current_thread()展现当前进度,threading.active_count()当前历程活跃个数

“`

  • 此处结果为二秒多或多或少,总结时间准确,用于此现象时,join()必须在有着线程的start()之后,不然成为二十多线程串行,二10十2线程就无意义了

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)

 

主线程不是守护线程(也不得设置为照拂线程),不等待子线程(设置为守护线程)等待2秒的日子,直接实行最终一句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)

  • 互斥锁(线程锁)
    同时只允许2个线程改变数据,而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地图