Variable passed to multiple threads of the same function

旧巷老猫 提交于 2020-02-25 06:41:05

问题


I am currently working on a system that sends webhooks to multiple Discord using dhooks.

This is the function used to call the function which sends the webhooks. The length of webhooks is 2 and it's a list of lists.

for hook in webhooks:
    thread.start_new_thread(send_hook,(hook, embed, tag))

This is the send_hook function:

def send_hook(hook, embed, tag):

    embed.set_footer(text="{} x Will".format(hook[0])) <-- This is the part where the error happens

    webhook = Webhook(hook[1])
    webhook.send(embed=embed)

The error I am getting is, when I set the footer in line 2 of send_hook, the variable inserted into the embed variable is sometimes sent to the wrong webhooks - almost as if its being over ridden.

As an example:

This is my list webhooks: [["Webhook 1 text", "discordwebhook1"], ["Webhook 2 text", "discordwebhook1"]].

What will happen is that in the channel of discordwebhook1 the footer will say "Webhook 1 text", but in the channel of discordwebhoo2 the footer will say "Webhook 1 text" as-well.

I have tried creating a new variable of the embed in the send_hook function - however this also didn't work (code below).

def send_hook(hook, embed, tag):
    new_embed = embed
    new_embed.set_footer(text="{} x Will".format(hook[0])) <-- This is the part where the error happens

    webhook = Webhook(hook[1])
    webhook.send(embed=new_embed)

I appreciate all help!

Thanks


回答1:


How do you get 'embed'? Notice that 'embed' and 'tag' are always passed to every newly created thread, you need to do a deepcopy of each if necessary

from copy import deepcopy

for hook in webhooks:
    thread.start_new_thread(send_hook,(hook, deepcopy(embed), tag))



回答2:


You are experiencing a race condition. Two threads have access to the same variable, and they are both modifying the variable. The outcome of your program depends on which one reaches the code that changes the variable first.

There are two possible solutions, depending on how you want the problem to be resolved:

  1. If you don't need all threads to share the same value, or if the object is small and cheap to copy, make a copy of the variable you are passing before you pass it, by passing deepcopy(embed) instead of embed - see the solution posted by @user1438644 for code.

  2. If you want all threads to share the same value, or if it is expensive to make copies of the object, you will need to create a lock with my_lock = threading.Lock(), and when you get to the race condition part of your program (i.e., the part that modifies the shared variable), surround it with a context manager with my_lock:, which acquires the lock at the start and returns the lock when finished. For example:

import threading
my_lock = threading.Lock()

# your code here

for hook in webhooks:
    threading.Thread(send_hook, args=(hook, embed, tag))

# more code here

def send_hook(hook, embed, tag):
    # Ensure embed is only changed by one thread at a time
    with my_lock:
        print("Lock acquired")
        embed.set_footer(text="hello world")
        webhook = Webhook(hook[1])
        webhook.send(embed=embed)


来源:https://stackoverflow.com/questions/58309718/variable-passed-to-multiple-threads-of-the-same-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!