Python 线程、进程和协程

python提供了两个模块来实现多线程thread 和threading ,thread 有一些缺点,在threading 得到了弥补,为了不浪费时间,所以我们直接学习threading 就可以了。

Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*- 
 3 
 4 import threading
 5 import time
 6 
 7 def show(arg):
 8     time.sleep(1)
 9     print 'thread'+str(arg)
10 
11 for i in range(10):                 #开启10个线程
12     t = threading.Thread(target=show, args=(i,)) #创建线程t,使用threading.Thread()方法,在这个方法中调用show方法target=show,args方法对show进行传参。
13                                                     
14     t.start()
15 print 'main thread stop'

上述代码创建了10个“前台”线程,然后控制器就交给了CPU,CPU根据指定算法进行调度,分片执行指令。

  python中的多线程,有一个GIL(Global Interpreter Lock 全局解释器锁 )在同一时间只有一个线程在工作,他底层会自动进行上下文切换.这个线程执行点,那个线程执行点!

更多方法:

    start()         线程准备就绪,等待CPU调度

    setName       为线程设置名称

    getName     获取线程名称

    setDaemon     setDaemon(True)将线程声明为前台线程,必须在start() 方法调用之前设置
              如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止
              如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止

     join         逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义    

     run         线程被cpu调度后执行Thread类对象的run方法

线程锁

由于线程之间是进行随机调度,并且每个线程可能只执行n条执行之后,CPU接着执行其他线程。所以,可能出现抢占屏幕打印问题,出现乱序问题,执行上面的代码可以直接看到效果.所以就出现了线程锁机制,专门解决这个问题.

设置线程锁

python的锁可以独立提取出来

#锁的使用
#创建锁
lock= threading.Lock()
#锁定
lock.acquire([timeout])#锁定方法acquire可以有一个超时时间的可选参数timeout。如果设定了timeout,则在超时后通过返回值可以判断是否得到了锁,从而可以进行一些其他的处理。
#释放
lock.release()

设置线程锁:

 1 #!/usr/bin/env python
 2 #coding:utf-8
 3 
 4 import threading
 5 import time
 6 
 7 gl_num = 0
 8 lock = threading.RLock()        #创建线程锁
 9 
10 def Func():
11     lock.acquire()              #锁定
12     global gl_num
13     gl_num +=1
14     time.sleep(1)
15     print gl_num
16     lock.release()              #释放锁
17 
18 for i in range(10):
19     t = threading.Thread(target=Func)
20 
21     t.start()

event

他的作用就是:用主线程控制子线程合适执行,他可以让子线程停下来,也可以让线程继续! 他实现的机制就是:标志位“Flag”

事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。

clear:将“Flag”设置为False

set:  将“Flag”设置为True

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*- 
 3 
 4 import threading
 5 
 6 def do(event):
 7     print 'start'
 8     event.wait() #执行对象wait方法,然后他们停下来,等待“Flag”为True
 9     print 'execute'
10 
11 event_obj = threading.Event()   #创建事件的对象
12 
13 for i in range(10):
14     t = threading.Thread(target=do, args=(event_obj,))  #把方法do传到每个线程里面,
15     t.start()
16 
17 event_obj.clear()   #设置"Flag"为Flase
18 
19 inp = raw_input('input:')
20 if inp == 'true':
21     event_obj.set()

 Python 线程、进程和协程

 multiprocessing是要比fork更高级的库了,使用multiprocessing可以更加轻松的实现多进程程序。

#!/usr/bin/env python
# -*- coding:utf-8 -*- 
from multiprocessing import Process
import threading
import time

def foo(i):
    print 'say hi',i

for i in range(10):
    p = Process(target=foo,args=(i,))
    p.start()

注意:由于进程之间的数据需要各自持有一份,所以创建进程需要的非常大的开销。并且python不能再Windows下创建进程!

使用多进程的时候,最好是创建和和CPU核数相等的进程数?:

 

进程数据共享

进程各自持有一份数据,默认无法共享数据

默认的进程之间相互是独立,如果想让进程之间数据共享,就得有个特殊的数据结构,这个数据结构就可以理解为他有穿墙的功能 如果你能穿墙的话两边就都可以使用了

 

#!/usr/bin/env python
#coding:utf-8
 
from multiprocessing import Process
from multiprocessing import Manager
import time
 
li = []
 
def foo(i):
    li.append(i)
    print 'say hi',li
  
for i in range(10):
    p = Process(target=foo,args=(i,))
    p.start()
     
print 'ending',li

使用特殊的数据类型,来进行穿墙:

#通过特殊的数据结构:数组(Array)

from multiprocessing import Process,Array

#创建一个只包含数字类型的数组(python中叫列表)
#并且数组是不可变的,在C,或其他语言中,数组是不可变的,之后再python中数组(列表)是可以变得
#当然其他语言中也提供可变的数组
#在C语言中数组和字符串是一样的,如果定义一个列表,如果可以增加,那么我需要在你内存地址后面再开辟一块空间,那我给你预留多少呢?
#在python中的list可能用链表来做的,我记录了你前面和后面是谁。   列表不是连续的,数组是连续的

'''
上面不是列表是“数组"数组是不可变的,附加内容是为了更好的理解数组!
'''

temp = Array('i', [11,22,33,44]) #这里的i是C语言中的数据结构,通过他来定义你要共享的内容的类型!点进去看~
 
def Foo(i):
    temp[i] = 100+i
    for item in temp:
        print i,'----->',item
 
for i in range(2):
    p = Process(target=Foo,args=(i,))
    p.start()
    
第二种方法:
#方法二:manage.dict()共享数据
from multiprocessing import Process,Manager  #这个特殊的数据类型Manager
 
manage = Manager()
dic = manage.dict() #这里调用的时候,使用字典,这个字典和咱们python使用方法是一样的!
 
def Foo(i):
    dic[i] = 100+i
    print dic.values()
 
for i in range(2):
    p = Process(target=Foo,args=(i,))
    p.start()
    p.join() 
1     'c': ctypes.c_char,  'u': ctypes.c_wchar,
2     'b': ctypes.c_byte,  'B': ctypes.c_ubyte,
3     'h': ctypes.c_short, 'H': ctypes.c_ushort,
4     'i': ctypes.c_int,   'I': ctypes.c_uint,
5     'l': ctypes.c_long,  'L': ctypes.c_ulong,
6     'f': ctypes.c_float, 'd': ctypes.c_double
类型对应表

相关文章:

  • 2021-07-17
  • 2021-09-03
  • 2021-05-19
  • 2021-11-25
  • 2021-10-19
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-12-08
  • 2021-12-30
  • 2021-11-06
  • 2022-02-28
相关资源
相似解决方案