• 线程安全问题


     - 先来看一段代码

    import time
    
    class Foo(object):
        pass
    
    foo = Foo()
    
    def add(i):
        foo.num = i
        time.sleep(1)
        print(foo.num)
    
    for i in range(20):
        add(i)

     - 结果是每一秒输出一个,假如一个网站同时有20个用户来进行访问,每一个人加载代码需要一秒,那么对后访问的人体验非常差,这个时候我们就需要开启线程

     - 代码改进

    import time
    import  threading
    
    class Foo(object):
        pass
    
    foo = Foo()
    
    def add(i):
        foo.num = i
        time.sleep(1)
        print(foo.num,i)
    
    for i in range(20):
        threading.Thread(target=add,args=(i,)).start()

     - 此时的结果为,这样还是行不通

    19 0
    19 1
    19 4
    19 5
    19 2
    19 3
    19 8
    19 9
    19 6
    19 7
    19 12
    19 14
    19 15
    19 11
    19 10
    19 13
    19 17
    19 18
    19 16
    19 19
    View Code

     - 解决方法

    import time
    import  threading
    from threading import local 
    class Foo(local):
        pass
    
    foo = Foo()
    
    def add(i):
        foo.num = i
        time.sleep(1)
        print(foo.num,i)
    
    for i in range(20):
        threading.Thread(target=add,args=(i,)).start()

     - 结果

    0 0
    2 2
    3 3
    1 1
    5 5
    6 6
    4 4
    8 8
    7 7
    9 9
    12 12
    10 10
    11 11
    14 14
    16 16
    15 15
    13 13
    19 19
    17 17
    18 18
    View Code

     - 为什么继承了local 就成功了呢?

     - 首先要知道

    threading.current_thread().ident # 线程id

     - local本质其实是通过唯一的线程ID来进行取值的

     - 来看一段伪代码

    """
    {
        1616 : foo.num = 0, 
        13128 : foo.num = 1,
        13540 : foo.num = 2,
    }
    """

     - local 会拿出这么一块空间来存储对应关系,从而达到最快效率的运算,其实就是用空间来换取时间

    节省时间 ----> 开线程 -----> 线程安全 -----> 占用空间

  • 相关阅读:
    典型用户和场景总结
    排球的详细记分规则
    js 实现全选
    博客搬家啦!
    leetcode #980 不同路径||| (java)
    ADV-299 宰羊 (java,过了30%)
    ADV-292 计算行列式 java
    ADV-302 秘密行动 java
    ADV-297 快速排序 java
    ADV-298 和谐宿舍2 动态规划
  • 原文地址:https://www.cnblogs.com/lzmdbk/p/10245552.html
Copyright © 2020-2023  润新知