python 多线程与多进程

一 线程的概念与描述
  并行运行这些相互独立的多任务,因此提出了多线程编程的概念,主线程应该是个线程的管理者,应该知道子线程的工作,以便于管理
  正是由于全局锁的关系,使得线程只能够一个个的取访问,也就是python是假的多线程,但是正式这种特性使得它更适合io密集型的操作,比如互联网文件的存取
'''
    import threading 模块
    th=threading.Thread(target=函数名) 创建一个线程,线程的命名空间为函数内
    th.start() 开启线程
    th.join()    表示线程等待,默认的永久等待.
    th.getName() 表示获取线程的名字
    th.ident()   表示获取id地址(硬件)
   len(threading.enumerate())  查看线程的数量
'''
多线程共享全局变量,有注意多线程可能会产生资源的抢占问题。可以通过全局锁来解决这个问题
'''
nux=Threading.LOCK()  直接将线程锁当做参数,传递给创建线程的函数
nux.acquire()  开启锁,将全局变量要修改的部分进行锁定。
nux.release()     关闭锁,让其以的线程可以进行全局变量的修改
threading.Thread(target=函数名,args=(nux,)) 向函数传递值
'''
线程锁代码实例:
import threading
import time

g_num = 0

def test1(num):
    global g_num
    for i in range(num):
        mutex.acquire()  # 上锁
        g_num += 1
        mutex.release()  # 解锁

    print("---test1---g_num=%d"%g_num)

def test2(num):
    global g_num
    for i in range(num):
        mutex.acquire()  # 上锁
        g_num += 1
        mutex.release()  # 解锁

    print("---test2---g_num=%d"%g_num)

# 创建一个互斥锁
# 默认是未上锁的状态
mutex = threading.Lock()

# 创建2个线程,让他们各自对g_num加1000000次
p1 = threading.Thread(target=test1, args=(1000000,))
p1.start()

p2 = threading.Thread(target=test2, args=(1000000,))
p2.start()

# 等待计算完成
while len(threading.enumerate()) != 1:
    time.sleep(1)

print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)
View Code
线程锁:当有竞争的时候,可以设置一个线程锁,线程锁是当线程竞争资源的时候,谁先触发线程锁,就会将全局变量进行创建临界区,锁住允许第一个获得锁的线程进入临街区,并执行代码。等待线程的执行完毕
线程的优缺点:
   1,多进程的优点是创建的进程需要的资源大
   2,多线程的缺点是由于所有的线程共享资源,一个线程死亡,整个进程就会崩溃
   3,多进程与多线程数量越多就会越消耗资源。因为连续的切换作用
   4,异步指的是异步io操作,io操作,与cpu操作能够随时切换,就像异步一样。

不过我们平时很少使用多线程,多进程外加协程。  
二 进程:
  1,进程是系统分配资源的最小单位,线程是程序执行的最小单位。
  2,进程之间是无序的,与操作系统的调度策略有关
  3创建子进程的过程就会对父进程的代码进行复制。线程之间的通信,可以通过Queue 队列类来进行通信
  4,多少个进程有几个cpu ,8个核有8个进程,当你开启16个进程,还是争夺8个cpu 。不能达到16个并行,是并行和并发一起抢夺资源.
  5,一个进程最多打开课1024个文件
'''
from multiprocessing import Process,Queue

pro=Process(target='函数名',args=(q,))    通过元组进行传参,创建一个进程函数,将队列传进去
pro.start() 开启进程
pro.join() 表示进程等待,参数是等待时间,超过时间就会执行下面的代码。
pro.is_alive() 表示进程的子进程是否存活
pro.terminate() 不管进程程是否存在,进行终止进程的操作,有操作系统来完成,有一定的时间延迟
os.getpid() 返回当前进程的进程号!  os 与进程相互使用,
os.getppid() 返回父进程的进程号

q=Queue(3) #初始化一个队列
q.put('1') 向队列里面进行传参数
q.full() 如果返回为True 表示队列已经满了,不会抛异常,只会等待
q.name  表示返回进程的名字
q.empty()  表示队列是否为空
q.get() 得到变量,先进先出

'''
队列的用法实例:
#coding=utf-8
from multiprocessing import Queue
q=Queue(3) #初始化一个Queue对象,最多可接收三条put消息
q.put("消息1") 
q.put("消息2")
print(q.full())  #False
q.put("消息3")
print(q.full()) #True

#因为消息列队已满下面的try都会抛出异常,第一个try会等待2秒后再抛出异常,第二个Try会立刻抛出异常
try:
    q.put("消息4",True,2)
except:
    print("消息列队已满,现有消息数量:%s"%q.qsize())

try:
    q.put_nowait("消息4")
except:
    print("消息列队已满,现有消息数量:%s"%q.qsize())

#推荐的方式,先判断消息列队是否已满,再写入
if not q.full():
    q.put_nowait("消息4")

#读取消息时,先判断消息列队是否为空,再读取
if not q.empty():
    for i in range(q.qsize()):
        print(q.get_nowait())
View Code
进程通过队列来通信实例:
from multiprocessing import Process, Queue
import os, time, random

# 写数据进程执行的代码:
def write(q):
    for value in ['A', 'B', 'C']:
        print('Put %s to queue...' % value)
        q.put(value)
        time.sleep(random.random())

# 读数据进程执行的代码:
def read(q):
    while True:
        if not q.empty():
            #Queue.get([block[, timeout]]):获取队列中的一条消息,然后将其从列队中移除,block默认值为True
            value = q.get(True)
            print('Get %s from queue.' % value)
            time.sleep(random.random())
        else:
            break

if __name__=='__main__':
    # 父进程创建Queue,并传给各个子进程:
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    # 启动子进程pw,写入:
    pw.start()    
    # 等待pw结束:
    pw.join()
    # 启动子进程pr,读取:
    pr.start()
    pr.join()
    # pr进程里是死循环,无法等待其结束,只能强行终止:
    print('')
    print('所有数据都写入并且读完')
View Code

 

posted @ 2018-05-10 10:56  十七楼的羊  阅读(168)  评论(0编辑  收藏  举报