GIL锁,线程锁(互斥锁)和递归锁

GIL锁(Global Interpreter Lock):CPython才会有(是这种解释器的历史遗留问题),Python程序执行前,先获得GIL锁,然后每执行100个指令,解释器就自动释放GIL锁,让别的线程执行。所以,多线程在Python中只能交替执行,同一时间只有一个线程在执行。

Python多线程一般应用于IO密集型程序,不适合用于CPU密集型(以计算为主)程序,因为线程之间的上下文切换也需要时间。如下面例子,多线程不如单线程效率高:

两线程串行:

#coding=utf-8

import threading
import time


def computed():
    i = 0
    for n in xrange(100000000):
        i += 1

thread_list = []

for _ in range(2):
    time_begin = time.time()
    thread_list.append(threading.Thread(target=computed))
    thread_list[_].start()
    thread_list[_].join()

print '两线程串行总运行时间:{}'.format(time.time() - time_begin)

# 两线程串行总运行时间:3.20499992371

两线程并行

#coding=utf-8

import threading
import time


def computed():
    i = 0
    for n in xrange(100000000):
        i += 1

thread_list = []

for _ in range(2):
    time_begin = time.time()
    thread_list.append(threading.Thread(target=computed))
    thread_list[_].start()

for t in range(2):
    thread_list[t].join()

print '两线程并行总运行时间:{}'.format(time.time() - time_begin)

# 两线程并行总运行时间:23.4430000782

线程锁是什么?为什么有了GIL锁还需要线程锁?

在多线程的运算中,可能一个线程执行了100个指令,在切换到了另一个线程的时候,由于它没有计算完毕,而且另一个线程也操作同一个内存对象,这样很容易出现混乱。

说具体点儿,比如一个线程把内存中的a,加1加到一半,切换到另一个线程,另一个线程也是对a加1,且已经加完,并把结果赋给了内存中的a(可以理解为另一个线程的操作不需要这么多指令?),然后第一个线程还是把之前a的值加1,并不是从内存中重新读取再加,所以第一个线程加完之后把结果赋给内存,这样就相当于另一个线程没加上。为了避免这样的问题出现,所以使用线程锁。

#coding=utf-8

import threading
import time

n, thread_list = 0, []

def computed():
    global n
    n += 1

for _ in xrange(10000):
    thread_list.append(threading.Thread(target=computed))
    thread_list[_].start()

for t in thread_list:
    t.join()

print n

递归锁

#coding=utf-8

import threading

def run1():
    print 'grab the first part data'
    lock.acquire()
    global num
    num += 1
    lock.release()
    return num

def run2():
    print 'grab the second part data'
    lock.acquire()
    global num2
    num2 += 1
    lock.release()
    return num2

def run3():
    lock.acquire()
    res = run1()
    print '-------between run1 and run2------'
    res2 = run2()
    lock.release()
    print res, res2


num, num2 = 0, 0
lock = threading.Lock()
for i in range(10):
    t = threading.Thread(target=run3)
    t.start()

while threading.active_count() != 1:
    print threading.active_count()
else:
    print '---all threads done---'
    print num, num2

感觉就是锁的嵌套,结果会不停返回“11”,出现混乱。解决方案用递归锁threading.Rlock()。

原文地址:https://www.cnblogs.com/allenzhang-920/p/10176895.html