首页 > 解决方案 > 如何在这里避免竞争条件

问题描述

getUrl如果我使用线程运行它会出现竞争条件吗?我正在更改data['key']多个线程中的值。我需要将整个传递data给我提出的请求,基本上,一组键将被固定,只有命名的键key会因我进行的每个线程调用而改变

import requests
from concurrent.futures import ThreadPoolExecutor


def getUrl(url, value):
    data['key'] = value # will there be a race condition here
    return requests.get(url, data=data).text # and when the value is passed here

data = {'key': 1, 'fixedKey': 'fixedValue', 'fixedKey2': 'fixedValue2'}
resultArray = []
threadPool = ThreadPoolExecutor(32)

for i in range(100):
    resultArray.append(threadPool.submit(getUrl, 'https://google.com', i))

Python字典中的线程安全我检查了这个,但我的困惑是当我进行设置时线程切换上下文data['key'] = value,然后其他一些线程更改它并且下一行现在具有由不同线程设置的新值。

例子

Value set by thread 1
data['key'] = 1
Context Switch
Value set by thread 2
data['key'] = 2
Context Switch back to old thread 1
is data['key'] = `2` now? I would necessarily want the value `1`

如果我使用锁,那么我将在这里失去并发性。

标签: python

解决方案


存在竞争条件,因为data在线程之间共享并且您从它们中对其进行了变异。

可视化这种竞争条件的一种简单方法是使用 a和模拟request调用:sleepprint

from concurrent.futures import ThreadPoolExecutor
from time import sleep

def getUrl(url, value):
    data['key'] = value
    sleep(0.3)
    print(value, data["key"])

data = {'key': 1, 'fixedKey': 'fixedValue', 'fixedKey2': 'fixedValue2'}
resultArray = []
threadPool = ThreadPoolExecutor(32)

for i in range(100):
    resultArray.append(threadPool.submit(getUrl, 'https://google.com', i))

您会看到传递给的值getUrl有时与存储在data.

data一种解决方案是在对其进行变异之前在本地复制。


推荐阅读