python - 如何使用上下文管理器锁定
问题描述
我一直在尝试越来越多地弄清楚上下文管理器,而且我越深入,我似乎发现的问题就越多。我目前的问题是我目前没有锁,这可能导致两个或多个线程最终可能具有相同的共享值,因为我只希望使用一个值。
import random
import threading
import time
list_op_proxy = [
"https://123.123.12.21:12345",
"http://123.123.12.21:54321",
]
proxy_dict = dict(zip(list_op_proxy, ['available'] * len(list_op_proxy)))
proxy_dict['http://123.123.12.21:987532'] = "busy"
class AvailableProxies:
def __enter__(self):
while True:
available = [att for att, value in proxy_dict.items() if "available" in value]
if available:
self.proxy = random.choice(available)
proxy_dict[self.proxy] = "busy"
return self.proxy
else:
continue
def __exit__(self, exc_type, exc_val, exc_tb):
proxy_dict[self.proxy] = "available"
def handler(name):
with AvailableProxies() as proxy:
print(f"{name} | Proxy in use: {proxy}")
# Adding 2 seconds as we want to see if it actually wait for the availability
time.sleep(2)
for i in range(5):
threading.Thread(target=handler, args=(f'Thread {i}',)).start()
正如您在我的上下文管理器中看到的那样,我想随机循环一个字典键:值,它的值设置为可用,如果它可用,那么我们将它设置为忙-> 做一些事情然后退出它(通过设置释放相同的值可用) - 但是我的问题是,在极少数情况下,似乎超过 2 个线程能够获得我想要阻止的相同代理,我希望只有一个线程能够访问上下文管理器时间,所以我们可以将代理值设置为忙,这样其他线程就不能接受它。
如何锁定以便只有一个线程可以将代理设置为忙,这样就不会发生两个或多个线程在同一个代理上设置为忙?
解决方案
您只需要在查找代理时锁定并在找到代理后释放锁定(用法与您之前的问题相同,无论您是否使用上下文管理器),我只是添加了一些调试消息:
import random
import threading
import time
list_op_proxy = [
"https://123.123.12.21:12345",
"http://123.123.12.21:54321",
]
proxy_dict = dict(zip(list_op_proxy, ['available'] * len(list_op_proxy)))
proxy_dict['http://123.123.12.21:987532'] = "busy"
proxy_lock = threading.Lock()
class AvailableProxies:
def __enter__(self):
proxy_lock.acquire()
self.proxy = None
while not self.proxy:
available = [
att for att, value in proxy_dict.items() if "available" in value
]
if available:
print('%d proxies available' % len(available))
self.proxy = random.choice(available)
proxy_dict[self.proxy] = "busy"
break
else:
print("Waiting ... not proxy available")
time.sleep(.2)
continue
proxy_lock.release()
return self.proxy
def __exit__(self, exc_type, exc_val, exc_tb):
proxy_dict[self.proxy] = "available"
def handler(name):
with AvailableProxies() as proxy:
print(f"{name} | Proxy in use: {proxy}")
# Adding 2 seconds as we want to see if it actually wait for the availability
time.sleep(.1)
for j in range(5):
threads = [threading.Thread(target=handler, args=(i, )) for i in range(3)]
[t.start() for t in threads]
[t.join() for t in threads]
print("---")
出去:
2 proxies available
0 | Proxy in use: http://123.123.12.21:54321
1 proxies available
1 | Proxy in use: https://123.123.12.21:12345
Waiting ... not proxy available
2 proxies available
2 | Proxy in use: https://123.123.12.21:12345
---
2 proxies available
0 | Proxy in use: http://123.123.12.21:54321
1 proxies available
1 | Proxy in use: https://123.123.12.21:12345
Waiting ... not proxy available
2 proxies available
2 | Proxy in use: http://123.123.12.21:54321
---
2 proxies available
0 | Proxy in use: https://123.123.12.21:12345
1 proxies available
1 | Proxy in use: http://123.123.12.21:54321
Waiting ... not proxy available
2 proxies available
2 | Proxy in use: https://123.123.12.21:12345
---
2 proxies available
0 | Proxy in use: https://123.123.12.21:12345
1 proxies available
1 | Proxy in use: http://123.123.12.21:54321
Waiting ... not proxy available
2 proxies available
2 | Proxy in use: https://123.123.12.21:12345
---
2 proxies available
0 | Proxy in use: http://123.123.12.21:54321
1 proxies available
1 | Proxy in use: https://123.123.12.21:12345
Waiting ... not proxy available
2 proxies available
2 | Proxy in use: http://123.123.12.21:54321
---
推荐阅读
- ios - CoreBlutooth 属性正在返回奇怪的状态
- python - 用范围内的随机值替换 NaN
- uml - 在用例图中正确使用包含和扩展
- python - 我想用scrapy输出预期的JSON
- ssl - 将 BoringSSL 与 Hazelcast IMDG 一起使用的正确配置设置是什么?
- controller - TypeError:无法读取 null 的属性“toString”
- python - 单词搜索算法找不到某些单词
- reactjs - 在数组上使用推送时重复条目
- javascript - antd:单选按钮作为卡片
- javascript - 什么相当于javascript中的numpy.repeat()