Python--进程与线程

一,回顾操作系统的概念

操作系统位于底层硬件与应用软件之间的一层

工作方式:向下管理软件,向上提供接口

二,进程线程的概念

  进程是一个资源单位,线程是一个最小的执行单位

    一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程

三,并行与并发

并行:
    就是有多个进程可以同时运行的叫做并行
并发:
    就是在一个处理器的情况下,切换执行,叫做并发

python无法实现并行处理,因为全局解释器锁gil导致同一时刻同一进程
只能有一个线程被运行。

GIL全局解释器锁
    但是不影响Python开多进程

多线程代码示例

import threading
import time
‘‘‘
程序在运行是有一个主线程,当程序开启多线程的时候,主线程依旧会执行,
主线程执行到最后时,并没有结束,而是在等待子线程的结束后主线程结束

‘‘‘
def misc():
    print("听歌")
    time.sleep(3)
    print("听歌结束")

def xieboke():
    print("写博客")
    time.sleep(5)
    print("写博客结束")

#开启线程
t1=threading.Thread(target=misc)#t1,t2是一个线程对象
t2=threading.Thread(target=xieboke)

t1.start()
t2.start()

print("主线程")

#开启多线程的另一种方式

import threading
import time
class MyThread(threading.Thread):
    ‘‘‘
    用类的继承,继承线程的方法开启线程
    ‘‘‘

    def __init__(self,num):
    ‘‘‘
    继承父类的__init__方法
    ‘‘‘
        threading.Thread.__init__(self)
        self.num=num

    def run(self):
        print("running on mythread:%s"%self.num)
        time.sleep(3)
        print("end%s"%self.num)

t1=MyThread(10)
t2=MyThread(20)

t1.start()
t2.start()
print("主线程")

jion的使用
    t.jion方法会阻塞主进程的运行,但不会影响其他线程的运行

setDaemon方法
    -守护线程
    当某个线程设置为守护线程的时候,它会随着主线程的结束而结束
    t.setDaemon(True)
    
线程对象下的几个方法:
        -isAlive()检测线程是否活动,返回值是布尔值
        -getName():返回线程名
        -setName():设置线程名称
        
threading模块提供的一些方法:
    threading.currentTread():返回当前线程变量
    threading.enumerate():返回一个包含正在运行的线程的list。
    threading.activeCount():返回正在运行的线程数量
    
Python对于计算密集型运行比较慢,效率低;对于IO密集型效率有明显提高

Python多线程
    互斥锁:
        互斥锁的意义就是在保护锁内代码同一时间只有一个线程在使用
        直到代码执行完成,解锁后其他线程才能执行所内代码。
    使用格式:
        -lock=threading.Lock()创建一把锁的对象
        lock.acquire()#加锁
        ....需要保护的执行语句
        lock.release()#解锁
    
    死锁与递归锁    
    代码示例:

       import threading
        import time

        muteA=threading.Lock()
        muteB=threading.Lock()

        class MyThread(threading.Thread):
            def __init__(self):
                threading.Thread.__init__(self)

            def run(self):
                self.func1()
                self.func2()

            def func1(self):
                muteA.acquire()
                print("锁A执行内容",MyThread.getName(self))
                muteB.acquire()
                print("锁B执行内容",MyThread.getName(self))
                muteB.release()
                muteA.release()

            def func2(self):
                muteB.acquire()
                print("第二个函数的锁B",MyThread.getName(self))
                muteA.acquire()
                print("第二个函数的锁A",MyThread.getName(self))
                muteA.release()
                muteB.release()

        if __name__=="__main__":
            for i in range(10):
                my_thread=MyThread()
                my_thread.start()

形成死锁的原因在于当线程1在第二个函数中拿到锁B向下执行需要锁A的时候,线程2在函数1中
    已经拿到的锁A,在等待线程1释放B。两个线程都没有释放另一个线程需要的锁,所以就形成了死锁。
    
    
    递归锁的应用
    递归锁未避免死锁的产生,在锁内实行一个引用计数,当有一把使用是计速器加一,释放后,去除计数
    到代码在执行锁内代码时,如果有其他线程抢锁,计数如果为零,线程可以拿到锁,大于零,拒绝线程拿锁
    这样就能避免锁的重复,也就不会产生死锁
    代码示例:    
    import threading
        import time

Rlock=threading.Rlock()

class MyThread(threading.Thread):
            def __init__(self):
                threading.Thread.__init__(self)

def run(self):
                self.func1()
                self.func2()

def func1(self):
                Rlock.acquire()
                print("锁A执行内容",MyThread.getName(self))
                Rlock.acquire()
                print("锁B执行内容",MyThread.getName(self))
                Rlock.release()
                Rlock.release()

def func2(self):
                Rlock.acquire()
                print("第二个函数的锁B",MyThread.getName(self))
                Rlock.acquire()
                print("第二个函数的锁A",MyThread.getName(self))
                Rlock.release()
                Rlock.release()

if __name__=="__main__":
            for i in range(10):
                my_thread=MyThread()
                my_thread.start()
                
event方法使用:
    event方法可以让两个线程之间通信,当一个线程需要另一个线程准备数据的时候,
    event.wait(),阻塞程序的运行,直到另一个线程将数据准备完成后,使用event.set()
    返回一个true值,event.wait()接受到该值之后,线程开始运行。wait方法后可以接一个超时
    时间参数,规定在一定时间内阻塞,超时后运行。
    
    import threading
    import time
    import logging

logging.basicConfig(level=logging.DEBUG, format=‘(%(threadName)-10s) %(message)s‘,)

def worker(event):
        logging.debug(‘Waiting for redis ready...‘)

while not event.isSet():
            logging.debug("wait.......")
            event.wait(3)   # if flag=False阻塞,等待flag=true继续执行

logging.debug(‘redis ready, and connect to redis server and do some work [%s]‘, time.ctime())
        time.sleep(1)

def main():

readis_ready = threading.Event()  #  flag=False创建一个event对象
        t1 = threading.Thread(target=worker, args=(readis_ready,), name=‘t1‘)
        t1.start()

t2 = threading.Thread(target=worker, args=(readis_ready,), name=‘t2‘)
        t2.start()

logging.debug(‘first of all, check redis server, make sure it is OK, and then trigger the redis ready event‘)

time.sleep(6) # simulate the check progress
        readis_ready.set()  # flag=Ture

if __name__=="__main__":
        main()

进程multprocessing模块

multprocessing模块与threading模块使用同一套api,使用方法调用方法与threading模块一样
    
    代码示例:
    from multiprocessing import Process

import time

def f(name):
        print("hello",name,time.ctime())
        time.sleep(1)

if __name__=="__main__":
        p_list=[]
        for i in range(3):
            p=Process(target=f,args=("alvin:%s"%i,))
            p_list.append(p)
            p.start()
    
    
协程的应用:
    协程是单线程的,不能切换。因为协程对IO操作的判断由自己控制
    import time

#  可以实现并发

def consumer():

r = ‘‘
        while True:

n = yield r
            if not n:
                return
            print(‘[CONSUMER] ←← Consuming %s...‘ % n)
            time.sleep(1)
            r = ‘200 OK‘

def produce(c):

next(c)
        n = 0
        while n < 5:
            n = n + 1
            print(‘[PRODUCER] →→ Producing %s...‘ % n)

cr = c.send(n)

print(‘[PRODUCER] Consumer return: %s‘ % cr)

c.close()

if __name__==‘__main__‘:

c = consumer()
        produce(c)
    
gevent模块的使用:
    from gevent import monkey
    monkey.patch_all()

import gevent
    from urllib import request
    import time

def f(url):
        print(‘GET: %s‘ % url)
        resp = request.urlopen(url)
        data = resp.read()
        print(‘%d bytes received from %s.‘ % (len(data), url))

start=time.time()

gevent.joinall([
             gevent.spawn(f, ‘https://itk.org/‘),
             gevent.spawn(f, ‘https://www.github.com/‘),
             gevent.spawn(f, ‘https://zhihu.com/‘),
     ])

#f(‘https://itk.org/‘)
    #f(‘https://www.github.com/‘)
    #f(‘https://zhihu.com/‘)

print(time.time()-start)  

时间: 2024-11-05 16:00:24

Python--进程与线程的相关文章

Python编程(二):Python进程、线程那点事儿

多进程,多线程编程 系统程序员.运维开发程序员在面试的时候经常会被问及一个常见问题: 进程是什么,线程是什么,进程和线程有什么区别? 不得不承认,这么多年了.这个问题依旧是个很难以招架的问题,简单地说: 进程和线程有很多类似的性质,他们都可以被CPU作为一个单元进行调度,他们都拥有自己独立的栈(stack)等等.因此线程也被称作LWP(Lightweight Process,轻量级进程):对应的进程也可以被称作为HWP(Heavyweight Process,重量级进程),从线程的角度看,进程就

python 进程、线程 (二)

一.多线程与多进程的对比 在python 进程.线程 (一)中简单的说过,CPython中的GIL使得同一时刻只能有一个线程运行,即并发执行.并且即使是多核CPU,GIL使得同一个进程中的多个线程也无法映射到多个CPU上运行,这么做最初是为了安全着想,慢慢的也成为了限制CPython性能的问题. 就像是一个线程想要执行,就必须得到GIL,否则就不能拿到CPU资源.但是也不是说一个线程在拿到CPU资源后就一劳永逸,在执行的过程中GIL可能会释放并被其他线程获取,所以说其它的线程会与本线程竞争CPU

python\进程和线程2

1  GIL全局解释器锁定义 定义:在一个线程拥有了解释器的访问权后,其他的所有线程都必须等待他释放解释器的访问权,即这些线程的下一条指令并不会互相影响. 缺点:多处理器退化为单处理器 优点:避免大量的加锁解锁操作 无论你启多少个线程,你有多少个cpu,python在执行一个进程的时候会淡定的在同一时刻只允许一个线程运行. Python是无法利用多核cpu实现多线程的 总结: 对于计算密集型任务,python的多线程并没有用 对于IO密集型任务,python的多线程是有意义的 python使用多

python进程、线程、协程

进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. 程序是运行在系统上的具有某种功能的软件,比如说浏览器,音乐播放器等. 每次执行程序的时候,都会完成一定的功能,比如说浏览器帮我们打开网页,为了保证其独立性,就需要一个专门的管理和控制执行程序的数据结构--进程控制块. 进程就是一个程序在一个数据集上的一次动态执行过程. 进程一般由程序.数据集.进程控

Python进程与线程及GIL(全局解释器锁)

MarkdownPad Document 进程与线程 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种一个程序在一个数据集上的一次动态执行过程就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本:进程是程序的一次执行活动,属于动态概念.进程一般由程序.数据集.进程控制块三部分组成. 有了进程为什么还要有线程呢? 因为进程还是有缺陷的: 进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了 进程在执行的过程中如果阻塞,例

Python进程、线程、协程详解

进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. 程序是运行在系统上的具有某种功能的软件,比如说浏览器,音乐播放器等. 每次执行程序的时候,都会完成一定的功能,比如说浏览器帮我们打开网页,为了保证其独立性,就需要一个专门的管理和控制执行程序的数据结构——进程控制块. 进程就是一个程序在一个数据集上的一次动态执行过程. 进程一般由程序.数据集.进程控

[ Python - 14 ] python进程及线程编程

什么是进程: 简单来讲,进程就是操作系统中运行的程序或任务,进程和程序的区别在于进程是动态的,而程序是静态的.进程是操作系统资源管理的最小单位. 什么是线程: 线程是进程的一个实体,是cpu调度和分派的最小单位,它是比进程更小的能独立运行的基本单位,线程本身不拥有资源,但它可以与同属于一个进程的线程共享进程的资源所拥有的全部资源. python多线程编程与GIL: 为了更有效的利用多核处理,就出现了多线程编程,但是问题是线程间数据的一致性和状态的同步如果得到保证,因此python解析器引入了GI

Python 进程、线程、协程、锁机制,你知多少?

1.python的多线程到底有没有用? 2. 为什么在python里推荐使用多进程而不是多线程 3.进程.线程.协程.各种锁

python进程、线程、协程以及几种自定义线程池

Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. #!/usr/bin/env python # -*- coding:utf-8 -*- import threading import time    def show(arg):     time.sleep(1)     print 'thread'+str(arg)    for i in range(10):     t = threading.Thread(target=show, args

Python进程与线程

进程与线程:*进程: 进程是系统中程序执行和资源分配的基本单元, 每个进程都有自己的数据段(存储数据).代码段(存储代码).堆栈段(对象和变量). # 全局变量等资源在多个进程中不能            共享, 在子进程中修改全局变量对父进程中的全局变量没有影响. *线程: 在一个进程内要同时干多件事, 就得同时运行多个"子任务", 这些子任务称为线程; 每个线程共享这个进程的所有资源(变量和数据等)和内存空间, 所以在子线程里面可以修改该            进程的变量.*多任务