本文转载自:https://blog.csdn.net/qq_33961117/article/details/87645427

目录

一、local 简单介绍

1-1 不使用local组件存在的弊端

二、Local组件的简单使用 - local对象.变量名 = 赋值

2-1 自定义字典实现Local的操作

2-2 基于面对对象实现Local

2-3 基于魔法方法实现Local

2-4 基于魔法方法实现单独存储空间的Local

三、实现Local并使其兼容线程和协程 - 参考Flask源码


一、local 简单介绍

python3 - 多线程 - threading 模块(基于win系统)- Thread、Timer 组件

当多个线程修改同一个数据时,将该数据复制多份给每个线程单独使用,即为每个线程开辟一块空间进行数据存储

1-1 不使用local组件存在的弊端

多个线程同时操作同一个全局变量,每次操作都会修改值,存在锁机制。导致每个线程取到的起始数据不相同,导致最后结果输出错误。

  1. # 未使用local
  2. from threading import Thread
  3. import time
  4. test= -1
  5. def task(arg):
  6. global test
  7. test= arg
  8. # 模拟IO操作,用于实现对全局变量的混乱操作
  9. time.sleep(2)
  10. print(test)
  11. for i in range(10):
  12. t = Thread(target=task,args=(i,))
  13. t.start()
  14. '''
  15. 9
  16. 9
  17. 9
  18. 9
  19. 9
  20. 9
  21. 9
  22. 9
  23. 9
  24. 9
  25. '''

二、Local组件的简单使用 - local对象.变量名 = 赋值

总结:由Local组件的简单使用可以看出Local操作类似于字典的操作。

  1. from threading import Thread
  2. from threading import local
  3. import time
  4. from threading import get_ident # get_ident用于获取线程、进程ID号
  5. # 初始化local对象
  6. loc= local()
  7. def task(arg):
  8. # 对象.val = 1/2/3/4/5
  9. loc.value = arg
  10. time.sleep(2)
  11. print(loc.value)
  12. for i in range(10):
  13. t = Thread(target=task,args=(i,))
  14. t.start()
  15. '''
  16. 3
  17. 1
  18. 0
  19. 2
  20. 5
  21. 4
  22. 7
  23. 6
  24. 9
  25. 8
  26. '''

2-1 自定义字典实现Local的操作

  1. from threading import get_ident,Thread
  2. import time
  3. storage = {}
  4. def set(k,v):
  5. ident = get_ident()
  6. if ident in storage:
  7. storage[ident][k] = v
  8. else:
  9. storage[ident] = {k:v}
  10. def get(k):
  11. ident = get_ident()
  12. return storage[ident][k]
  13. def task(arg):
  14. set('val',arg)
  15. v = get('val')
  16. print(v)
  17. for i in range(10):
  18. t = Thread(target=task,args=(i,))
  19. t.start()

2-2 基于面对对象实现Local

  1. from threading import get_ident,Thread
  2. import time
  3. class Local(object):
  4. storage = {}
  5. def set(self, k, v):
  6. ident = get_ident()
  7. if ident in Local.storage:
  8. Local.storage[ident][k] = v
  9. else:
  10. Local.storage[ident] = {k: v}
  11. def get(self, k):
  12. ident = get_ident()
  13. return Local.storage[ident][k]
  14. obj = Local()
  15. def task(arg):
  16. obj.set('val',arg)
  17. v = obj.get('val')
  18. print(v)
  19. for i in range(10):
  20. t = Thread(target=task,args=(i,))
  21. t.start()

2-3 基于魔法方法实现Local

  1. from threading import get_ident,Thread
  2. import time
  3. class Local(object):
  4. storage = {}
  5. def __setattr__(self, k, v):
  6. ident = get_ident()
  7. if ident in Local.storage:
  8. Local.storage[ident][k] = v
  9. else:
  10. Local.storage[ident] = {k: v}
  11. def __getattr__(self, k):
  12. ident = get_ident()
  13. return Local.storage[ident][k]
  14. obj = Local()
  15. def task(arg):
  16. obj.val = arg
  17. print(obj.val)
  18. for i in range(10):
  19. t = Thread(target=task,args=(i,))
  20. t.start()

2-4 基于魔法方法实现单独存储空间的Local

  1. from threading import get_ident,Thread
  2. import time
  3. class Local(object):
  4. def __init__(self):
  5. object.__setattr__(self,'storage',{})
  6. def __setattr__(self, k, v):
  7. ident = get_ident()
  8. if ident in self.storage:
  9. self.storage[ident][k] = v
  10. else:
  11. self.storage[ident] = {k: v}
  12. def __getattr__(self, k):
  13. ident = get_ident()
  14. return self.storage[ident][k]
  15. obj = Local()
  16. def task(arg):
  17. obj.val = arg
  18. obj.xxx = arg
  19. print(obj.val)
  20. for i in range(10):
  21. t = Thread(target=task,args=(i,))
  22. t.start()

三、实现Local并使其兼容线程和协程 - 参考Flask源码

  1. try:
  2. from greenlet import getcurrent as get_ident
  3. except Exception as e:
  4. from threading import get_ident
  5. from threading import Thread
  6. import time
  7. class Local(object):
  8. def __init__(self):
  9. object.__setattr__(self,'storage',{})
  10. def __setattr__(self, k, v):
  11. ident = get_ident()
  12. if ident in self.storage:
  13. self.storage[ident][k] = v
  14. else:
  15. self.storage[ident] = {k: v}
  16. def __getattr__(self, k):
  17. ident = get_ident()
  18. return self.storage[ident][k]
  19. obj = Local()
  20. def task(arg):
  21. obj.val = arg
  22. obj.xxx = arg
  23. print(obj.val)
  24. for i in range(10):
  25. t = Thread(target=task,args=(i,))
  26. t.start()

Python3 - 多线程 - threading 模块(基于win系统)- local组件

 

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-28
  • 2022-02-06
  • 2021-07-30
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-11-23
  • 2021-07-15
  • 2022-01-04
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案