python多线程锁实战_Python多线程锁

在多线程程序执行过程中,为什么需要给一些线程加锁以及如何加锁,下面就来说一说。

1.给线程加锁的原因

我们知道,不同进程之间的内存空间数据是不能够共享的,试想一下,如果可以随意共享,谈何安全?但是一个进程中的多个线程是可以共享这个进程的内存空间中的数据的,比如多个线程可以同时调用某一内存空间中的某些数据(只是调用,没有做修改)。

试想一下,在某一进程中,内存空间中存有一个变量对象的值为num=8,假如某一时刻有多个线程需要同时使用这个对象,出于这些线程要实现不同功能的需要,线程A需要将num减1后再使用,线程B需要将num加1后再使用,而线程C则是需要使用num原来的值8。由于这三个线程都是共享存储num值的内存空间的,并且这三个线程是可以同时并发执行的,当三个线程同时对num操作时,因为num只有一个,所以肯定会存在不同的操作顺序,想象一下下面这样操作过程:

因为num只有一个,而三个操作都针对一个num进行,所以上面的操作过程是完全有可能的,而原来线程A、B、C想要使用的num值应该分别为:7、9、8,这里却变成了:8、8、7。试想一下,如果这三个线程的操作对整个程序的执行是至关重要的,会造成什么样的后果?

因此出于程序稳定运行的考虑,对于线程需要调用内存中的共享数据时,我们就需要为线程加锁。

2.Python多线程锁

(1)

先看下面一个未给线程加锁的程序代码:

程序执行结果如下:

上面是多个线程同时抢占同一内存空间的例子,但从执行结果中可以看到,程序依然顺序地输出1-19,而没有出现上面说的情况,那是仅仅是因为量少的原因,虽然执行正常,没有出错,但是并不代表不会出错。

(2)

看下面给线程加锁的代码:

程序执行结果如下:

程序的执行结果肯定是会正常的,而在没有给线程加锁之前,则有可能是正常,注意这是两种完全不同的概念。

分析一下上面的程序:在某一线程修改num的值时,即给该线程加锁,该线程加锁后,只要是该线程需要调用的代码以及涉及的内存空间,都会立即被锁上,比如这里的"number+=1",其它线程虽然也在并发同时执行,但是不能执行"number+=1"这行代码的,即不能够去访问或修改num这一个共享内存空间的数据,只能等待该线程解锁后才能执行;当该线程解锁后,另一个线程马上加锁再来修改number的值,同时也不允许其它线程占用,如此类推,直到所有线程执行完毕。

根据上面的分析,为线程加锁就可以解决前面讲的线程安全问题。

(3)

为了更好的理解线程加锁的一个过程,把上面的代码修改为如下:

执行结果如下:

程序的执行结果跟上面是完全一样,但是程序的执行过程却大不一样,这里说一下修改代码后程序的执行过程:每输出一个数字,sleep 1秒后再输出下一个数字,如此类推。

为了更好的说明,我们可以看一下执行完此程序所花的时间:

由执行时间可以更好的说明上面的执行过程,但为什么会这样呢?下面来分析一下:由(2)的分析可知,虽然20个线程都是在同时并发执行run这一个函数,这里与(2)不同在于,(2)只加锁了涉及修改number的程序代码,而这里是加锁了整一个函数!所以在20个线程同时开始并发执行这个函数时,由于每一个线程的执行都要加锁,并且加锁的是整一个执行的函数,因此其它线程就无法调用该函数中的程序代码,只能等待一个线程执行完毕后再调用该函数的程序代码,如此一来,一个线程的执行需要sleep(1)一次,则20个线程的执行就需要sleep(1)20次,并且该过程是串行的,因此我们才看到如上面所说的程序执行过程,也可以清晰的知道为什么程序的执行需要20s了。

由上面的分析,我们不仅可以知道为什么要给线程加锁以及如何加锁,还可以比较清楚的知道线程加锁的一个过程了,以后在编写程序的时候,类似情况的,我们就应该要为线程加锁。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值