Python并行编程(三):线程同步Lock

dukuan 2018-10-10 原文


Python并行编程(三):线程同步之Lock


 

1、基础概念

      当两个或以上对共享内存操作的并发线程中,如果有一个改变数据,又没有同步机制的条件下,就会产生竞争条件,可能会导致执行无效代码、bug等异常行为。

      竞争条件最简单的解决方法是使用锁。锁的操作非常简单,当一个线程需要访问部分共享内存时,它必须先获得锁才能访问。此线程对这部分共享资源使用完成之后,释放锁,然后其他线程才可再次获得锁并访问这部分资源。

      然而,在实际使用中,这个方法经常导致死锁现象。当不同线程要求得到同一个锁时,死锁就会发生,此时程序不会继续执行,因为他们互相拿着对方需要的锁。

      

      造成死锁的原因:线程A在使用资源2,线程B在使用资源1,如果在没有释放锁时,线程A又需要资源1,线程B又需要资源2,但是两个资源的锁都是被占用的,而且在对方的锁释放之前都处于等待且不释放锁的状态,此时就会造成死锁。

      使用锁来解决同步问题是一个可行的方式,但是也存在潜在的问题。

2、使用Lock进行线程同步

      示例:

# coding : utf-8

import threading

shared_resource_with_lock = 0
shared_resource_with_no_lock = 0
count = 100000

shared_resource_lock = threading.Lock()

# has lock
def increment_with_lock():
    global shared_resource_with_lock
    for i in range(count):
        shared_resource_lock.acquire()
        shared_resource_with_lock += 1
        shared_resource_lock.release()
def decrement_with_lock():
    global shared_resource_with_lock
    for i in range(count):
        shared_resource_lock.acquire()
        shared_resource_with_lock -= 1
        shared_resource_lock.release()

# has no lock
def increment_without_lock():
    global shared_resource_with_no_lock
    for i in range(count):
        shared_resource_with_no_lock += 1

def decrement_without_lock():
    global shared_resource_with_no_lock
    for i in range(count):
        shared_resource_with_no_lock -= 1

if __name__ == "__main__":
    t1 = threading.Thread(target=increment_with_lock)
    t2 = threading.Thread(target=decrement_with_lock)
    t3 = threading.Thread(target=increment_without_lock)
    t4 = threading.Thread(target=decrement_without_lock)
    t1.start()
    t2.start()
    t3.start()
    t4.start()
    t1.join()
    t2.join()
    t3.join()
    t4.join()
    print("the value of shared with lock is %s" %shared_resource_with_lock)
    print("the value of shared with no lock is %s" % shared_resource_with_no_lock)

      执行结果:

      

      在有锁的情况下,我们会得到挣钱的结果,而没有锁的情况下,往往会出现错误的结果。

3、锁状态

      锁有两种状态:locked(被某一线程拿到)和unlocked(可用状态)

      操作锁的方式:acquire()和release()

      如果状态是unlocked,可以调用acquire将状态改为locked

      如果状态是locked,acquire会被block直到另一个线程调用release释放锁

      如果状态是unlocked,调用release会导致RuntimError异常

      如果状态是locked,可以调用release将状态改为unlocked

 

 

版权声明:本文为dukuan原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/dukuan/p/9766955.html

Python并行编程(三):线程同步Lock的更多相关文章

随机推荐

  1. 设计模式那些事

    什么是设计模式?我们为什么要学习和使用设计模式?设计模式又有哪些?这里博主根据自己所了解的内容做一简单介绍。 […]...

  2. 手把手教你用GoEasy实现Websocket IM即时通讯

    经常有朋友问起GoEasy如何实现IM,今天就手把手的带大家从头到尾用GoEasy实现一个完整IM聊天,全套代 […]...

  3. (数据科学学习手札50)基于Python的网络数据采集-selenium篇(上)

    一、简介   接着几个月之前的(数据科学学习手札31)基于Python的网络数据采集(初级篇),在那篇文章中, […]...

  4. 人脸识别一体机解决方案

    方案背景 得益于人工智能的技术日益发展,在计算机视觉的领域中,人脸识别的技术已经非常成熟。在商业应用中出现了大 […]...

  5. 十分钟教科书式教条,轻松搞定系统分析师的论文

    十分钟教科书式教条,轻松搞定系统分析师的论文 前言 因为我发现很多人考试都是死在论文上的。平时学习时,对论文也 […]...

  6. JS实现购物车动态功能

    整理了一下当时学js写的一些案例,觉得购物车功能在一般网站比较常见且基础,现在把它整理出来,需要的小伙伴可以参 […]...

  7. kubernetes生产实践之mysql

    简介 kubedb mysql 生命周期及特性 Supported MySQL Features Featur […]...

  8. 011.MongoDB性能监控

    一 MongoDB 监控 1.1 监控概述 MongoDB自带了mongostat 和 mongotop 这两 […]...

展开目录

目录导航