ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

互斥量适合于快速单写/慢速阅读器(cpython)?

2019-10-31 17:58:53  阅读:237  来源: 互联网

标签:multithreading mutex shared-memory python


在我的应用程序中,我有一个单线程正在对日志行执行非常快速的处理以产生浮点值.通常只有一个其他线程按一定间隔对值进行慢速读取.每隔一段时间,其他线程就会来来往往,并对这些值执行一次性读取.

我的问题是关于互斥锁(在cpython中)的必要性,对于这种特定情况,其中数据只是可用的最新数据.它不是必须与其他任何内容(甚至是其他同时写入的字段)同步的关键值.只是……价值是什么.

话虽如此,我知道我可以轻松地添加一个锁(或读取器/写入锁)来保护值的更新,但是我想知道整个日志过程中获取/释放的开销是否快速连续(假设平均5000行)仅“适当地”共享资源是不值得的.

根据What kinds of global value mutation are thread-safe?上的文档,这些分配应该是原子操作.

这是逻辑的基本示例:

import time
from random import random, choice, randint
from threading import Thread 

class DataStructure(object):
    def __init__(self):
        self.f_val = 0.0
        self.s_val = ""

def slow_reader(data):
    """ 
    Loop much more slowly and read values 
    anywhere between 1 - 5 second intervals
    """
    for _ in xrange(10):

        f_val = data.f_val 
        # don't care about sync here
        s_val = data.s_val

        print f_val, s_val

        # in real code could be even 30 or 60 seconds
        time.sleep(randint(1,3))

def fast_writer(data):
    """ Update data extremely often """
    for _ in xrange(20000):
        f_val, s_val = do_work()

        data.f_val = f_val
        # don't care about sync here
        data.s_val = s_val 


FLOAT_SRC = [random()*100 for _ in xrange(100)]
STR_SRC = ['foo', 'bar', 'biz', 'baz']

def do_work():
    time.sleep(0.001)
    return choice(FLOAT_SRC), choice(STR_SRC)


if __name__ == "__main__":

    data = DataStructure()

    threads = [
        Thread(target=slow_reader, args=(data,)),
        Thread(target=fast_writer, args=(data,)),
    ]

    for t in threads:
        t.daemon=True
        t.start()

    for t in threads:
        t.join()

这表示快速的日志解析器(实际上是通过PIPE读取)在每一行上工作,而慢速的定期阅读器此时获取的是当前值.任何时候,另一个曾经读过的线程都会来来去去,从数据结构中获取那些相同的值.

这是完全不需要cpython中的互斥锁的情况吗?

编辑

为了进一步说明…我什至不需要float和string字段与上一次写入保持同步.如果调度程序决定在浮点读取和字符串读取之间切换上下文是可以的.我只是想知道我是否甚至需要锁的开销来简单地读取随时分配的任何值.

我担心的是这样一个事实,即写程序将要以极快的操作循环,锁定和解锁通常没有竞争性的锁.

有效地假设这是我在读者中关心的全部内容:

def slow_reader(data):
    for _ in xrange(10):
        f_val = data.f_val 
        print f_val
        time.sleep(randint(1,3))

解决方法:

在进行并发访问时,需要一个互斥锁:

>关于复合值,并且这些访问之一必须原子地在多个位置修改该值;
>关于简单值,并且这些访问中至少有两个正在写入.

在您的示例中,该值是复合值(2个字段),并且修改在多个位置(这2个字段)上进行,因此您应该放置一个互斥锁,以确保在两次修改之间不会安排阅读器.

编辑:如果读者不关心同步字段,那么您不需要互斥体.

标签:multithreading,mutex,shared-memory,python
来源: https://codeday.me/bug/20191031/1977598.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有