zoukankan      html  css  js  c++  java
  • 类 线程安全变量

    众所周知,Django有ORM和信号,每次通过ORM对数据库中的记录进行修改,都会触发一些信号(当然还有其他情况也会触发信号,不止是修改表).在实际工作中有这样一种需求,我们需要记录哪个人对哪些记录进行了哪些修改。如果是单线程的话,就很简单了,使用request_started或者request_finished信号即可提取出 当前请求的用户。然而实际上,一个服务不可能是单线程的,那么多线程情况下,依旧使用上面两个信号,多个线程修改表(也就是操作ORM中的类),用户肯定是不同的,那么谁又能保证某个用户就是我们想要记录的客户呢?这个时候,就需要确保类中的某个变量是线程安全的。

    # pylint:disable-all
    import threading
    from time import sleep
    
    
    class Test(object):
        name = 'unknown'
        thread = threading.local()   # 得到的是一个 <_thread._local object at 0x7f1cb57ecf10>
    
        def say(self):
            print('my name is: {}'.format(self.name))
            print('my thread name is: {}'.format(self.thread.name))
    
    
    def t(name):
        print('set name:{}'.format(name))  
        Test.name = name 
        Test.thread.name = name
        sleep(3)
        Test().say()
    
    
    def main():
        pools = []
        for idx in range(2):
            pools.append(threading.Thread(target=t, args=('thread{}'.format(idx),)))   # 开启两个线程
     
        [x.start() for x in pools]   # 分别启动两个线程(就粗略的认为它是启动吧,忽略run方法)
        [x.join() for x in pools]   # 主线程等待两个子线程的结束
    
    
    if __name__ == '__main__':
        main()
    #_______________________________________________________________________________________#
    # set name:thread0   #  第一个线程设置 name 和 thread.name 名为 thread0
    # set name:thread1  #  第二个线程设置 name 和 thread.name为 thread1
    #...  等待 3s
    # my name is: thread1    # 第一个线程的 name 变为了 thread1 
    # my thread name is: thread0  #  第一个线程 thread.name 是 thread0
    # my name is: thread1  # 第二个线程的 name 名为  thread1
    # my thread name is: thread1 第二个线程的 thread.name 名为  thread1
    

    从上面的打印信息来看,经过多个线程的操作,类的 name 变量发生了变化,而 thread.name 保持了不变。

    那么如何在 ORM 中修改呢?

    
    class RuleChangeRecord(models.Model):
    
        thread = threading.local()
    
        rucr_id = models.AutoField(primary_key=True)
        rucr_create_time = models.DateTimeField(auto_now_add=True)
        rucr_modify_time = models.DateTimeField(auto_now=True)
        rucr_user = models.CharField(max_length=255, **blank_null)
        rucr_action = models.CharField(max_length=20, choices=consts.ACTION_TYPE_ENUM)
        rucr_table_name = models.CharField(max_length=255)
        rucr_entry_id = models.IntegerField()
        rucr_field_changed = models.TextField(**blank_null)
        rucr_old = models.TextField(**blank_null)
        rucr_new = models.TextField(**blank_null)
    
     
        def save(self, force_insert=False, force_update=False, using=None,
                 update_fields=None):
            self.rucr_user = getattr(self.thread, 'user', None)
            return super(RuleChangeRecord, self).save(force_insert=force_insert, force_update=force_update,
                                                                   using=using, update_fields=update_fields)
    

    下面是关于 threading.local()更好,更详细的讲解:
    深入理解Python中的ThreadLocal变量(上)
    深入理解Python中的ThreadLocal变量(中)
    深入理解Python中的ThreadLocal变量(下)

  • 相关阅读:
    jq绑定on事件无效
    数字以0补全
    redis常用操作
    mysql数据操作日常
    centos端口映射
    centos7防火墙操作
    mysql5.7order by问题
    centos无法上网解决方法
    面试题
    ztree 获取子节点所有父节点的name的拼接
  • 原文地址:https://www.cnblogs.com/jijizhazha/p/8383841.html
Copyright © 2011-2022 走看看