好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

人生苦短之我用Python篇(线程/进程、threading模块:全局解释器锁gil/信号量/Eve

线程: 有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。是一串指令的集合。 线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。 在单个程序中同时运行多个线程完成不同的工作,称为多线程。 进程: qq 要以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,内存的管理,网络接口的调用等。。。 对各种资源管理的集合 就可以成为进程。

进程 要操作cpu , 必须要先创建一个线程, all the threads in a process have the same view of the memory 所有在同一个进程里的线程是共享同一块内存空间的

进程与线程的区别?

Threads share the address space of the process that created it; processes have their own address space.
线程共享内存空间,进程的内存是独立的
Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.

Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes.
同一个进程的线程之间可以直接交流,两个进程想通信,必须通过一个中间代理来实现

New threads are easily created; new processes require duplication of the parent process.
创建新线程很简单, 创建新进程需要对其父进程进行一次克隆

Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes.
一个线程可以控制和操作同一进程里的其他线程,但是进程只能操作子进程

Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process does not affect child processes.

threading模块

(2

#普通写法
= threading.Thread(target=run,args=(= threading.Thread(target=run,args=(
import timeimport threading
#类写法class MyThread(threading.Thread):def __init__(self,n,sleep_time):
        super(MyThread, self).__init__()
        self.n = n
        self.sleep_time = sleep_timedef run(self):print("task", self.n)
        time.sleep(self.sleep_time)print("task done")

t1 = MyThread("t1",2)
t2 = MyThread("t2",4)

t1.start()
t2.start()

 

import threadingimport timedef run(n):print("task ",n )
    time.sleep(2)print("task done",n)

start_time = time.time()
t_objs = [] #存线程实例for i in range(50):
    t = threading.Thread(target=run,args=("t-%s" %i ,))
    t.start()
    t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里for t in t_objs: #循环线程实例列表,等待所有线程执行完毕    t.join()print(t_objs)print("----------all threads has finished...")print("cost:",time.time() - start_time)
Daemon:守护进程,即主进程一结束,守护进程也就结束
import threadingimport timedef run(n):print("task ",n )
    time.sleep(2)print("task done",n,threading.current_thread())

start_time = time.time()
t_objs = [] #存线程实例for i in range(50):
    t = threading.Thread(target=run,args=("t-%s" %i ,))
    t.setDaemon(True) #把当前线程设置为守护线程    t.start()
    t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里# for t in t_objs: #循环线程实例列表,等待所有线程执行完毕#     t.join()# time.sleep(2)print("----------all threads has finished...",threading.current_thread(),threading.active_count())print("cost:",time.time() - start_time)

 

全局锁

import threadingimport timedef run(n):
    lock.acquire()#获得锁,除非释放掉锁,否则其他线程就不能再次获得,2.7中试,3.0以后不需要了global  num
    num +=1# time.sleep(1)lock.release()#释放锁,其他线程可以获得了lock = threading.Lock()
num = 0
t_objs = [] #存线程实例for i in range(50):
    t = threading.Thread(target=run,args=("t-%s" %i ,))
    t.start()
    t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里for t in t_objs: #循环线程实例列表,等待所有线程执行完毕    t.join()print("----------all threads has finished...",threading.current_thread(),threading.active_count())print("num:",num)

 

 

 

 

 

 信号量:即同时可以获得多个锁

import threadingimport timedef run(n):
    semaphore.acquire()#信号量获取time.sleep(1)print("run the thread :%s\n" %n)
    semaphore.release()#信号量释放if __name__ == "__main__":
    semaphore = threading.BoundedSemaphore(5)   #设置信号量,即绑定信号量可以同时拥有的锁的数量for i in range(22):
        t = threading.Thread(target = run,args = (i,))
        t.start()while threading.active_count() !=1 :#当前活跃的线程数passelse:print("______-all threads done______")

Event:

event = threading.Event()
event.set()
event.clear()
event.is_set():#判断event是否设置了标志位

 红绿灯例子:

import timeimport threading

event = threading.Event()#生成event对象def lighter():
    event.set()#设置event标志位count = 0while True:if count >5 and count <10:
            event.clear()#清除event标志位print("\033[41;1m红灯亮....\033[0m")elif count > 10:
            event.set()print("\033[42;1m绿灯亮了....\033[0m")
            count = 0else:print("\033[42;1m绿灯亮着\033[0m")
        time.sleep(1)
        count +=1def car(n):while True:if event.is_set():#判断event是否设置了标志位print('\033[34;2m[%s] running..... \033[0m'%n)
            time.sleep(0.5)else:print('[%s] stoping.....'%n)
            event.wait()print('路灯亮了[%s]开跑'%n)


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

car1 = threading.Thread(target=car,args=('宝马',))
car1.start()

car2 = threading.Thread(target=car,args=('大奔驰',))
car2.start()

car3 = threading.Thread(target=car,args=('玛莎拉蒂',))
car3.start()

 

 

 

 

 

 

多进程:

和线程用法基本一致,我threading.Thread换成multiprocessing.Process

import time,threadingimport multiprocessingdef thread_run():print(threading.get_ident())def run(name):
    time.sleep(2)print("hellp",name)
    t = threading.Thread(target=thread_run,)
    t.start()if __name__ =="__main__":for i in range (10):
        p = multiprocessing.Process(target=run,args=("bob %s"%i,))#与线程用法基本机制p.start()

 

 数据在不同进程间进行交换

from multiprocessing import Process,Queuedef f(qq):
    qq.put([42,None,156161])if __name__ =="__main__":
    q =Queue()#可以在不同进程间交互使用p = Process(target=f,args=(q,))#把q作为参数传入    p.start()print(q.get())#父进程可以得到子进程中修改过的数据p.join()

 

 进程池

Note:  from multiprocessing import Process, Pool,freeze_support

 

  pool = Pool(processes=5)
  pool.apply_async(func=Foo, args=(i,), callback=Bar) #callback=回调,父进程操作  #pool.apply(func=Foo, args=(i,)) #串行  #pool.apply_async(func=Foo, args=(i,)) #并行
from  multiprocessing import Process, Pool,freeze_supportimport timeimport osdef Foo(i):
    time.sleep(2)print("in process",os.getpid())return i + 100def Bar(arg):print('-->exec done:', arg,os.getpid())if __name__ == '__main__':#window必须加这一句#freeze_support()pool = Pool(processes=5) #允许进程池同时放入5个进程print("主进程",os.getpid())for i in range(10):
        pool.apply_async(func=Foo, args=(i,), callback=Bar) #callback=回调#pool.apply(func=Foo, args=(i,)) #串行#pool.apply_async(func=Foo, args=(i,)) #并行print('end')
    pool.close()
    pool.join() #进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。.join()

 

 进程锁:变串行了

from multiprocessing import Process, Lockdef f(l, i):#l.acquire()print('hello world', i)#l.release()if __name__ == '__main__':
    lock = Lock()for num in range(100):
        Process(target=f, args=(lock, num)).start()

 

 

 Manager:进程间交换数据

from multiprocessing import Process, Managerimport osdef f(d, l):
    d[os.getpid()] =os.getpid()
    l.append(os.getpid())print(l)if __name__ == '__main__':
    with Manager() as manager:
        d = manager.dict() #{} #生成一个字典,可在多个进程间共享和传递l = manager.list(range(5))#生成一个列表,可在多个进程间共享和传递p_list = []for i in range(10):
            p = Process(target=f, args=(d, l))
            p.start()
            p_list.append(p)for res in p_list: #等待结果            res.join()print(d)print(l)

 

 Pipe:生成两个可以交互数据的进程

parent_conn, child_conn = Pipe()#生成两个可以交换数据的进程
from multiprocessing import Process, Pipedef f(conn):
    conn.send([42, None, 'hello from child'])
    conn.send([42, None, 'hello from child2'])print("from parent:",conn.recv())
    conn.close()if __name__ == '__main__':
    parent_conn, child_conn = Pipe()#生成两个可以交换数据的进程p = Process(target=f, args=(child_conn,))
    p.start()print(parent_conn.recv())  # prints "[42, None, 'hello']"print(parent_conn.recv())  # prints "[42, None, 'hello']"parent_conn.send("可好") # prints "[42, None, 'hello']"p.join()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
        

查看更多关于人生苦短之我用Python篇(线程/进程、threading模块:全局解释器锁gil/信号量/Eve的详细内容...

  阅读:42次