【进程与线程】概念、threading、生产者消费者模型

程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程python

程序和进程的区别:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念编程

进程的优势:提供了多道编程,让咱们感受咱们每一个人都拥有本身的CPU和其余资源,能够提升计算机的利用率。安全

进程的缺点多线程

  • 进程只能在一个时间干一件事,若是想同时干两件事或多件事,进程就无能为力了。
  • 进程在执行的过程当中若是阻塞,例如等待输入,整个进程就会挂起,即便进程中有些工做不依赖于输入的数据,也将没法执行并发

 

线程是操做系统可以进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运做单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中能够并发多个线程,每条线程并行执行不一样的任务app

 

io操做不占用CPU,计算占用CPU函数

python多线程不适合cpu密集操做型的任务,适合io操做密集型的任务ui

 

进程和线程的区别:spa

1.线程能够共享建立它的进程的地址空间;操作系统

   进程有它们各自的地址空间。

2.线程能够直接访问其进程的数据段;

   进程有本身的父进程的数据段副本。

3.线程能够直接与进程的其余线程通讯;

   进程必须使用进程间通讯与同级进程通讯。

4.新线程很容易建立;

   新进程须要复制它的父进程。

5.线程能够控制同一进程的线程;

   进程只能对子进程进行控制。

6.对主线程的更改(取消、优先级更改等)可能会影响该进程的其余线程;

   对父进程的更改不会影响子进程。

 

GIL锁(全局解释器锁Global Interpreter Lock)

在CPython中,全局解释器锁是防止多个本机线程同时执行Python字节码的互斥体。主要是由于CPython的内存管理不是线程安全的。

GIL并非Python的特性,Python彻底能够不依赖于GIL,可是GIL是CPython的特色。

 

python threading模块:

import threading

def run1(n):
    print('threading',n)

if __name__ == '__main__':
    for i in range(50):
        t = threading.Thread(target=run1, args=(i,))#实例化一个线程
        t.start()    #启动线程
        print(t.getName())    #获取线程名

 Join & Daemon:

import threading,time

def runm1(n):
    print('threading',n)
    time.sleep(2)
    print('run thread done')

def main():
    for i in range(10):
        t = threading.Thread(target=run1, args=(i,))  # 实例化一个线程
        t.start()
        t.join(1)
        print('starting threading',t.getName())

if __name__ == '__main__':
    m = threading.Thread(target=main)#实例化一个线程
    m.setDaemon(True) #将main设置为守护线程,当主线程结束时,主线程的守护线程就会当即结束
    m.start()    #启动线程
    m.join(timeout=2) #等待线程执行结束
    print('main thread done')    #获取线程名

 线程锁(互斥锁Mutex)

import threading,time

def run1():
    global n
    time.sleep(1)
    lock.acquire()#修改数据前加锁
    n+=1
    lock.release()#修改后释放

n=0
thread_list=[]
lock=threading.Lock() #生成全局锁

if __name__ == '__main__':
    for i in range(100):
        t=threading.Thread(target=run1)
        t.start()
        thread_list.append(t)
    for t in thread_list:
        t.join()
        print('num:', n)

    print('final num:',n)

GIL和Lock:
GIL为系统级的lock,Lock是用户级的lock与GIL无关

RLock(递归锁)

大锁中包含子锁时,防止lock的释放混乱

import threading

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是同时容许必定数量的线程更改数据,与互斥锁用法相同。

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)  # 实例化semaphore锁,最多容许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)

 threading.Timer()

等待必定的时间调用函数

import threading

def hello(name):
    print('hello %s\n'%name)
    global timer
    timer = threading.Timer(2.0, hello, ["q1ang"])
    timer.start()

if __name__ == "__main__":
    timer = threading.Timer(2.0, hello, ["q1ang"])
    timer.start()

 Events

 经过Event来实现两个或多个线程间的交互

import threading
import time

event=threading.Event()#实例化

def lighter():
    count=0
    event.set() #设置标志位
    while True:
        if  count>20 and count<30:#改为红灯
            event.clear() #清除标志位
            print('红灯',count)
        elif count>30:
            event.set()    #设置标志位
            count=0
        else:
            print('绿灯',count)
        time.sleep(1)
        count+=1
        print()

def car(name):
    while True:
        if event.is_set():#判断标志位启动,(绿灯
            print('run')
            time.sleep(1)
        else:
            print('wait')
            event.wait() #等待设定标志位
            print('start runing...')

light=threading.Thread(target=lighter,)
light.start()

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

queue队列(解耦)线程queue

class queue.Queue(maxsize=0) #先入先出

class queue.LifoQueue(maxsize=0) #last in fisrt out 后入先出

class queue.PriorityQueue(maxsize=0) #存储数据时可设置优先级的队列

import queue

q=queue.Queue(maxsize=3)

q.put('d1')
q.put('d2')
q.put('d3')

print(q.qsize())

print(q.get(block=False,timeout=1))
print(q.get(block=False,timeout=1))
print(q.get(block=False,timeout=1))

 生产者消费者模型:解耦

生产者消费者模式是经过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通信,而经过阻塞队列来进行通信,因此生产者生产完数据以后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就至关于一个缓冲区,平衡了生产者和消费者的处理能力。

在并发编程中使用生产者和消费者模式可以解决绝大多数并发问题。该模式经过平衡生产线程和消费线程的工做能力来提升程序的总体处理数据的速度。

import threading,time
import queue

q=queue.Queue(maxsize=10)

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

def Consumer(name):
    while True:
        print('[%s]取到[%s]并吃了它...'%(name,q.get()))
        time.sleep(2)

p=threading.Thread(target=Producer)
c1=threading.Thread(target=Consumer,args=('consumer1',))
c2=threading.Thread(target=Consumer,args=('consumer2',))

p.start()
c1.start()
c2.start()
相关文章
相关标签/搜索