前言

    在这里记录一下我学习线程锁的一些笔记

1.为什么要使用线程锁?

    使用线程锁的作用是为了保证数据的安全.
    举个例子:假设我们有一个全局变量n=0,创建20个线程,每个线程都执行n+=1,结果应该是20.但是会有这样一个问题:在执行第一个线程时,如果到了规定时间这个线程还没有执行完, 那么它只能暂时退出,先让其他的线程来执行.这样的话第一个线程没有执行完,那么此时n依然等于0.那么第二个线程拿到的n依然是0.这时候就会出现错误,因为这样的结果是第一个线程执行结果为1,第二个线程执行的结果也为1,最终20个线程执行的结果就是19,这样就会出现错误.
    我们来看下面这一段程序:

import threading
import time

start_time = time.time()

num = 0

def func():
    global num
    for i in range(100000):
        num += 1


thread_1 = threading.Thread(target=func)
thread_2 = threading.Thread(target=func)

thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()

print(num)

end_time = time.time()
print('cost time {}s'.format((end_time-start_time)))

    我们来分析一下这段代码:
    代码中定义了一个函数func,作用是对循环100000次num+1,然后定义了两个子线程,这样的话这段程序的结果就是200000,但是通过运行程序发现结果并不是200000,而且多运行几次,会发现每次的结果都不一样.至于具体原理,我们上边已经讲了.
下面是运行结果:

181710
cost time 0.03139781951904297s

2.什么是线程锁

    线程锁的意思是给每一个线程加上锁,当这个线程执行完成后才释放锁,下一个线程才能执行,这样就可以保证数据的安全准确,但是这样做就失去了并行的效果,所有的线程都是串行了.
    线程锁使用方式:

lock = threading.LOCK()		# 创建LOCK类实例
lock.acquire()				# 获取锁
lock.release()				# 释放锁,只有一个线程将锁释放了,另一个线程才能执行.

3.具体用法

    对于上面那个例子,我们加上线程锁:

import threading
import time


start_time = time.time()

threading_lock = threading.Lock()
num = 0

def func():
    global num
    for i in range(100000):
        threading_lock.acquire()        # 获得锁
        num += 1
        threading_lock.release()        # 释放锁


thread_1 = threading.Thread(target=func)
thread_2 = threading.Thread(target=func)

thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()

print(num)

end_time = time.time()
print('cost time {}s'.format((end_time-start_time)))

    加上锁以后再执行,发现结果是200000(运行了20次,每次都是200000),下面是运行结果:

200000
cost time 0.42098522186279297s

    作为对比,我们在做这种数值计算时,不用多线程,直接让func函数执行两次:

import threading
import time


start_time = time.time()

threading_lock = threading.Lock()
num = 0

def func():
    global num
    for i in range(100000):
        threading_lock.acquire()        # 获得锁
        num += 1
        threading_lock.release()        # 释放锁


func()
func()

print(num)

end_time = time.time()
print('cost time {}s'.format((end_time-start_time)))

    执行结果:

200000
cost time 0.07037591934204102s

天哪,使用多线程的时间竟然比不适用多线程的时间要多将近6倍!!!

    从这里我们也可以看出,多线程并不适合这种数值计算密集型的程序(即CPU操作密集型),但多线程对于I/O操作密集型的程序来说则是非常有用的.