进程、线程与GIL全局解释器锁详解

 (1)python下多线程的限制以及多进程中传递参数的方式
  python多线程有个全局解释器锁(global interpreter lock),这个锁的意思是任一时间只能有一个线程使用解释器,跟单cpu跑多个程序一个意思,大家都是轮着用的,这叫“并发”,不是“并行”。
  多进程间共享数据,可以使用 multiprocessing.Value 和 multiprocessing.Array

  (2)python多线程与多进程的区别  

    • 在UNIX平台上,当某个进程终结之后,该进程需要被其父进程调用wait,否则进程成为僵尸进程(Zombie)。所以,有必要对每个Process对象调用join()方法 (实际上等同于wait)。对于多线程来说,由于只有一个进程,所以不存在此必要性。

多进程应该避免共享资源。在多线程中,我们可以比较容易地共享资源,比如使用全局变量或者传递参数。在多进程情况下,由于每个进程有自己独立的内存空间,以上方法并不合适。此时我们可以通过共享内存和Manager的方法来共享资源。但这样做提高了程序的复杂度,并因为同步的需要而降低了程序的效率。

进程与线程的关系:

1.   线程是最小的调度单位
2.  进程是最小的管理单元
3.  一个进程必须至少一个线程
4.  没有线程,进程也就不复存在

线程特点:

3     线程的并发是利用cpu上下文的切换(是并发,不是并行4     多线程执行的顺序是无序的
5     多线程共享全局变量
6     线程是继承在进程里的,没有进程就没有线程
7     GIL全局解释器锁
8     只要在进行耗时的IO操作的时候,能释放GIL,所以只要在IO密集型的代码里,用多线程就    
9        很合适

线程详解:

import threading  # ---》导入模块
    # def func(n):
    #     print('task',n)
    # t = threading.Thread(target = func,args = (1,))
    # t.start()
    #
    #
    # for i in range(10):        ---》使t的内容循坏输出10行
    #     t = threading.Thread(target = func,args = ('t-%s'%i,))  ---》target=函数名 args要求以元组形式传参,当参数只有一个时,以(参数,)的格式传参。
    #     t.start()       ----》固定启动线程

    # 多线程共享全局变量

    # g=0    ---》设置一个全局变量
    # def test():
    #     global g              ----》线程共享全局变量时需要建立在声明global+全局变量上
    #     for i in range(10):
    #         g +=1
    #     print(g)
    # def test1():
    #     global g
    #     for i in range(10):
    #         g +=1
    #     print(g)
    # t1=threading.Thread(target=test)     ---->用线程调用test函数的结果,没有参数时,只需要输入target就行
    # t2=threading.Thread(target=test1)
    # t1.start()
    # t2.start()

 协程:

资源的自动切换,耗资源小,效率高。

GIL全局解释器锁:

#GIL全局解释器锁        ---》作用是保证最多只有一个线程在使用全局变量g_num,但是不保证赋值成功
lock = threading.Lock()   ----》添加互斥锁,作用是使两个线程不再并发处理,使赋值成功,注意L要大写
g_num = 0
def test1():
    global g_num
    lock.acquire()        ---》在循坏前锁上
    for i in range(100000):
        g_num +=1
    lock.release()      ----》赋值结束后解放锁
def test2():
    global g_num
    lock.acquire()
    for i in range(100000):
        g_num +=1
    lock.release()
t1=threading.Thread(target=test1)       ---》注意T要大写
t2=threading.Thread(target=test2)
t1.start()      #  导致结果不对的原因(1):主线程处理py文件速度比另外两个线程赋值速度快,在没赋值结束时就又开始新一轮的赋值
t2.start()

# 解决方法(1):
# 在后面加上两行
t1.join()   #----》即主线程等待每轮赋值结束后才重启下一轮赋值,但是这样也还是不对,只能让成功次数上升
t2.join()   # 因为赋值成功率不是100%,次数越多越有可能赋值失败。
print(g_num)

解决方法(2):
添加互斥锁:lock = threading.Lock() ,保证赋值成功,缺点是速度慢

进程详解:

# 一个程序运行起来之后,代码+用到的资源称之为进程,它是操作系统分配资源的基本单位,不仅可以通过线程完成多任务,进程也是可以的
# 进程之间是相互独立的,结果互不影响也无法共享全局变量,等待上一个进程结束,下一个进程再执行。
# cpu密集的时候适合用多进程
#cpu效率高,耗资源多,

import multiprocessing    --》导入进程模块
import time  ----》导入快捷键,将鼠标停在关键词上alt 加 enter 选择导入模块


def test1(n):
    time.sleep(2)       ---》两秒后打印执行任务完毕,再到第二个进程
    print('task',n)

def test2(n):
    time.sleep(2)
    print('task',n)
if __name__ == '__main__':    --->处理py文件,这是主进程的作用
    p1 = multiprocessing.Process(target=test1,args=(1,))     --》注意P的大写
    p2 = multiprocessing.Process(target=test2,args=(1,))
    p1.start()      ---》此进程负责调用p1进程
    p2.start()     ---》负责调用p2进程

进程池:

import multiprocessing
import time                   #进程池的并发必须导入和引用时间模块
g_num = 0
def test1(n):
    for i in range(n):
        time.sleep(1)
        print('test1', i)

def test2(n):
    for i in range(n):
        time.sleep(1)
        print('test2', i)
def test3(n):
    for i in range(n):
        time.sleep(1)
        print('test3', i)

def test4(n):
    for i in range(n):
        time.sleep(1)
        print('test4', i)

if __name__ == '__main__':                  #此操作必须存在,不然无法调用
    pool = multiprocessing.Pool(3)          #把进程声明出来括号里不写东西说明无限制,如果写数字,就是最大的进程数,即允许几个进程并发。池外的串行
    pool.apply_async(test1,(5,))           #用pool去调用函数test1,参数为5格式为(5,)
    pool.apply_async(test2,(5,))
    pool.apply_async(test3,(5,))
    pool.apply_async(test4,(5,))          #以上三个进程并发处理,同时输出赋值,而4进程串行输出,因为在进程池外**
    pool.close()
   pool.join() #close必须在join的前面

 

转载于:https://www.cnblogs.com/zzzynx/p/10774817.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值