ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python3 GIL锁/互斥锁Lock和递归锁Rlock

2019-06-16 16:48:46  阅读:291  来源: 互联网

标签:释放 Thread threading Lock Rlock 拿到 互斥 print GIL


GIL锁(Global Interpreter Lock)全局解释器锁
在Cpython解释器中,同一进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势.

那么,我们改如何解决GIL锁的问题呢?

  1.更换cpython为jpython(不建议)

  2.使用多进程完成多线程的任务

  3.在使用多线程可以使用c语言去实现

问题1: 什么时候会释放GIL锁?

1 遇到像 I/O操作这种 会有时间空闲情况 造成cpu闲置的情况会释放GIL
2 会有一个专门ticks进行计数 一旦ticks数值达到100 这个时候释放GIL锁 线程之间开始竞争GIL锁(说明:ticks这个数值可以进行设置来延长或者缩减获得Gil锁的线程使用cpu的时间)

问题2: 互斥锁和GIL锁的关系?

GIL锁 : 保证同一时刻只有一个线程能使用到cpu
互斥锁 : 多线程时,保证修改共享数据时有序的修改,不会产生数据修改混乱


首先假设只有一个进程,这个进程中有两个线程 Thread1,Thread2, 要修改共享的数据date, 并且有互斥锁

执行以下步骤

(1)多线程运行,假设Thread1获得GIL可以使用cpu,这时Thread1获得 互斥锁lock,Thread1可以改date数据(但并没有开始修改数据)

(2)Thread1线程在修改date数据前发生了 I/O操作 或者 ticks计数满100 (注意就是没有运行到修改data数据),这个时候 Thread1 让出了GIL,GIL锁可以被竞争

(3) Thread1 和 Thread2 开始竞争 GIL (注意:如果Thread1是因为 I/O 阻塞 让出的GIL Thread2必定拿到GIL,如果Thread1是因为ticks计数满100让出GIL 这个时候 Thread1 和 Thread2 公平竞争)

(4)假设 Thread2正好获得了GIL, 运行代码去修改共享数据date,由于Thread1有互斥锁lock,所以Thread2无法更改共享数据date,这时Thread2让出GIL锁 , GIL锁再次发生竞争


(5)假设Thread1又抢到GIL,由于其有互斥锁Lock所以其可以继续修改共享数据data,当Thread1修改完数据释放互斥锁lock,Thread2在获得GIL与lock后才可对data进行修改

以上描述了 互斥锁和GIL锁的 一个关系.


# -*- coding: utf-8 -*-
import time
from threading import Thread, Lock

n = 10
def func():
    with mutex:
        global n
        temp = n
        time.sleep(0.5)
        n = temp - 1


if __name__ == '__main__':
    '''线程之间数据是共享的,加锁来保护为了保护共享的数据,缺点线程变成了串行'''
    mutex = Lock()  # 线程不需要传递这把锁,子线程可以直接使用
    t_l = []
    for i in range(10):
        t = Thread(target=func)
        t_l.append(t)
        t.start()
    [tt.join() for tt in t_l]
    print(n)


# 0

 

# -*- coding: utf-8 -*-
import threading
from threading import Thread, Lock


def func():
    lockA.acquire()
    print("%s拿到A锁" % threading.current_thread().getName())
    lockB.acquire()
    print("%s拿到B锁" % threading.current_thread().getName())
    lockB.release()
    print("%s释放B锁" % threading.current_thread().getName())
    lockA.release()
    print("%s释放A锁" % threading.current_thread().getName())

    lockB.acquire()
    print("%s拿到B锁" % threading.current_thread().getName())
    lockA.acquire()
    print("%s拿到A锁" % threading.current_thread().getName())
    lockA.release()
    print("%s释放A锁" % threading.current_thread().getName())
    lockB.release()
    print("%s释放B锁" % threading.current_thread().getName())


if __name__ == '__main__':
    '''死锁现象,在同一进程的多个线程,一个线程所需要的锁,被另外一个线程抢到了'''
    lockA = Lock()
    lockB = Lock()
    for i in range(10):
        t = Thread(target=func)
        t.start()

# Thread-1拿到A锁
# Thread-1拿到B锁
# Thread-1释放B锁
# Thread-1释放A锁
# Thread-2拿到A锁
# Thread-1拿到B锁

 

# -*- coding: utf-8 -*-
import threading
from threading import Thread, RLock


def func():
    mutex.acquire()
    print("%s拿到锁" % threading.current_thread().getName())
    mutex.acquire()
    print("%s拿到锁" % threading.current_thread().getName())
    mutex.release()
    print("%s释放锁" % threading.current_thread().getName())
    mutex.release()
    print("%s释放锁" % threading.current_thread().getName())

    mutex.acquire()
    print("%s拿到锁" % threading.current_thread().getName())
    mutex.acquire()
    print("%s拿到锁" % threading.current_thread().getName())
    mutex.release()
    print("%s释放锁" % threading.current_thread().getName())
    mutex.release()
    print("%s释放锁" % threading.current_thread().getName())


if __name__ == '__main__':
    '''递归锁,是计数机制,acquire一次计数加一,release一次计数减一,只有计数为0的时候,线程间才是再次抢锁'''
    mutex = RLock()
    for i in range(10):
        t = Thread(target=func)
        t.start()

# Thread-1拿到锁
# Thread-1拿到锁
# Thread-1释放锁
# Thread-1释放锁
# Thread-2拿到锁
# Thread-2拿到锁
# Thread-2释放锁
# Thread-2释放锁
# Thread-1拿到锁
# Thread-1拿到锁
# Thread-1释放锁
# Thread-1释放锁
# Thread-2拿到锁
# Thread-2拿到锁
# Thread-2释放锁
# Thread-2释放锁
# Thread-3拿到锁
# Thread-3拿到锁
# Thread-3释放锁
# Thread-3释放锁
# Thread-4拿到锁
# Thread-4拿到锁
# Thread-4释放锁
# Thread-4释放锁
# Thread-5拿到锁
# Thread-5拿到锁
# Thread-5释放锁
# Thread-5释放锁
# Thread-3拿到锁
# Thread-3拿到锁
# Thread-3释放锁
# Thread-3释放锁
# Thread-6拿到锁
# Thread-6拿到锁
# Thread-6释放锁
# Thread-6释放锁
# Thread-4拿到锁
# Thread-4拿到锁
# Thread-4释放锁
# Thread-4释放锁
# Thread-7拿到锁
# Thread-7拿到锁
# Thread-7释放锁
# Thread-7释放锁
# Thread-5拿到锁
# Thread-5拿到锁
# Thread-5释放锁
# Thread-5释放锁
# Thread-8拿到锁
# Thread-8拿到锁
# Thread-8释放锁
# Thread-8释放锁
# Thread-9拿到锁
# Thread-9拿到锁
# Thread-9释放锁
# Thread-9释放锁
# Thread-6拿到锁
# Thread-6拿到锁
# Thread-6释放锁
# Thread-6释放锁
# Thread-10拿到锁
# Thread-10拿到锁
# Thread-10释放锁
# Thread-10释放锁
# Thread-7拿到锁
# Thread-7拿到锁
# Thread-7释放锁
# Thread-7释放锁
# Thread-8拿到锁
# Thread-8拿到锁
# Thread-8释放锁
# Thread-8释放锁
# Thread-9拿到锁
# Thread-9拿到锁
# Thread-9释放锁
# Thread-9释放锁
# Thread-10拿到锁
# Thread-10拿到锁
# Thread-10释放锁
# Thread-10释放锁

 

 

标签:释放,Thread,threading,Lock,Rlock,拿到,互斥,print,GIL
来源: https://www.cnblogs.com/lilyxiaoyy/p/11031986.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有