线程与进程锁

GIL全局解释器锁

Python代码的执行由Python虚拟机(也叫解释器主循环)来控制。Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行。虽然 Python 解释器中可以“运行”多个线程,但在任意时刻只有一个线程在解释器中运行。对Python虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。在多线程环境中,Python 虚拟机按以下方式执行:

  1. 设置 GIL;
  2. 切换到一个线程去运行;
  3. 运行指定数量的字节码指令或者线程主动让出控制(可以调用 time.sleep(0));
  4. 把线程设置为睡眠状态;
  5. 解锁 GIL;
  6. 再次重复以上所有步骤。

在调用外部代码(如 C/C++扩展函数)的时候,GIL将会被锁定,直到这个函数结束为止(由于在这期间没有Python的字节码被运行,所以不会做线程切换)编写扩展的程序员可以主动解锁GIL。

线程锁

from threading import Thread,Lock
x = 0
mutex = Lock()
def task():
    global x
    # mutex.acquire()
    for i in range(200000):
        x = x+1
        # t1 的 x刚拿到0 保存状态 就被切了
        # t2 的 x拿到0 进行+1       1
        # t1 又获得运行了  x = 0  +1  1
        # 思考:一共加了几次1? 加了两次1 真实运算出来的数字本来应该+2 实际只+1
        # 这就产生了数据安全问题.
    # mutex.release()
if __name__ == '__main__':
    t1 = Thread(target=task)
    t2 = Thread(target=task)
    t3 = Thread(target=task)
    t1.start()
    t2.start()
    t3.start()
    t1.join()
    t2.join()
    t3.join()
    print(x)
C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe D:/python/9.18/02线程锁.py
289103

数据量较大时用线程就会出现数据遗失问题,所以我们要加线程锁,保证数据的安全

死锁问题

from threading import Thread,Lock
mutex1 = Lock()
mutex2 = Lock()
import time
class MyThreada(Thread):
    def run(self):
        self.task1()
        self.task2()
    def task1(self):
        mutex1.acquire()
        print(f'{self.name} 抢到了 锁1 ')
        mutex2.acquire()
        print(f'{self.name} 抢到了 锁2 ')
        mutex2.release()
        print(f'{self.name} 释放了 锁2 ')
        mutex1.release()
        print(f'{self.name} 释放了 锁1 ')
    def task2(self):
        mutex2.acquire()
        print(f'{self.name} 抢到了 锁2 ')
        time.sleep(1)
        mutex1.acquire()
        print(f'{self.name} 抢到了 锁1 ')
        mutex1.release()
        print(f'{self.name} 释放了 锁1 ')
        mutex2.release()
        print(f'{self.name} 释放了 锁2 ')
for i in range(3):
    t = MyThreada()
    t.start()
# 两个线程
# 线程1拿到了(锁头2)想要往下执行需要(锁头1),
# 线程2拿到了(锁头1)想要往下执行需要(锁头2)
# 互相都拿到了彼此想要往下执行的必需条件,互相都不放手里的锁头,这样我们的程序就会卡在这。

信号量

from threading import Thread,currentThread,Semaphore
import time
def task():
    sm.acquire()
    print(f'{currentThread().name} 在执行')
    time.sleep(3)
    sm.release()
sm = Semaphore(5)
for i in range(15):
    t = Thread(target=task)
    t.start()
## 5个数据一组打印,相当于一个进程池

计算密集型问题用多进程

io密集型问题用多线程

posted @ 2019-09-18 15:12  oxtime  阅读(277)  评论(0编辑  收藏  举报