【问题标题】:Python Loss of data when running threadsPython运行线程时丢失数据
【发布时间】:2018-11-02 18:51:32
【问题描述】:

我有两个版本的相同程序执行相同的任务,一个使用线程模块,而另一个不使用。我要优化的任务如下

from random import randint
import time

t = time.time()

rolls = 25000
wins = 0
loss = 0

while rolls > 0:
    dice1 = randint(1, 6)
    dice2 = randint(1, 6)

    if dice1+dice2 == 11 or dice1+dice2 == 7 or dice1 == dice2:
        wins += 1
    else:
        loss += 1

    rolls -= 1

print(wins+loss)
percentage = (wins / wins+loss) * 100

print("Calculated percentage of a roll fulfilling requirements are:", 
round(percentage, 2), "%")
print(round((time.time()-t), 3))

正如您所希望的那样,我基本上想掷两个骰子一定次数,在这个例子中,这个数字是 25 000,然后打印出这两个骰子满足三个条件之一的机会,总和是 11 , 总和是 7 或者它们都具有相同的数字。

当然,我决定使用的掷骰数量会改变这个程序的结果,因为你走得越高,给出的答案就越准确。到目前为止一切顺利,程序按预期运行,胜负之和等于掷骰总数。

困扰我的是程序的线程版本。当我输入说,那里也有 25 000 卷时,我最终得到了大约 22 000 的总和,用于获胜 + 失败(这个总和因运行而异,为什么滚动消失?)运行线程版本的另一个副作用是胜率计算不太准确。

from random import randint
import threading
import time

t = time.time()

def dice_calc(rolls):
    global wins
    global loss
    while rolls > 0:

        dice1 = randint(1, 6)
        dice2 = randint(1, 6)

        if dice1+dice2 == 11 or dice1+dice2 == 7 or dice1 == dice2:
            wins += 1
        else:
            loss += 1

        rolls -= 1

wins = 0
loss = 0
rolls = 25000

t1 = threading.Thread(target=dice_calc, args=(rolls/4,))
t2 = threading.Thread(target=dice_calc, args=(rolls/4,))
t3 = threading.Thread(target=dice_calc, args=(rolls/4,))
t4 = threading.Thread(target=dice_calc, args=(rolls/4,))

t1.start()
t2.start()
t3.start()
t4.start()

print(wins+loss)

t1.join()
t2.join()
t3.join()
t4.join()

percentage = (wins / (wins+loss)) * 100

print("Calculated percentage of a roll fulfilling requirements are:", 
round(percentage, 2), "%")

print(round((time.time()-t), 3))

我使用这个线程模块的目的是提高程序的准确性,同时减少处理时间。我设法做到了完全相反的事情。

这怎么可能?我能做些什么来解决它?

【问题讨论】:

  • 您需要使用锁,因为如果两个或多个线程可以访问具有相同变量的相同代码,它们将会弄乱它们的数据。我需要复习我从课堂上得到的幻灯片,以便给你一个完整的答案

标签: python python-3.x multithreading


【解决方案1】:
def dice_calc(rolls):

    mutex.acquire() #Since you are using global variables you need to lock the code before the thread has access to the global

    global wins
    global loss
    while rolls > 0:

        dice1 = randint(1, 6)
        dice2 = randint(1, 6)

        if dice1+dice2 == 11 or dice1+dice2 == 7 or dice1 == dice2:
            wins += 1
        else:
            loss += 1

        rolls -= 1

    mutex.release() #Then you release it when it is finished

您需要在线程访问全局之前锁定代码,然后在完成处理后释放它。

一个很好的比喻:

你和三个朋友想从饮水机里喝一杯,你们每个人都需要等待轮到自己使用它,然后才能喝水。如果你们每个人同时去,它会变得一团糟,因为只有一个喷泉。喷泉是你的全局变量和代码,你和你的朋友是线程

【讨论】:

  • 我按照你说的做了,虽然它没有完全解决问题,但它确实使程序运行得更加一致。在 25 000 卷中,每次运行代码时,我现在得到 18 750 作为赢 + 输的总和。关于为什么我没有得到 100% 的回滚作为“胜利”和“失败”的更多见解?
  • @ToastyEngineer 哦,是的,查看我的多线程 C 代码,我使用了一种称为 volatile unsigned int 的东西作为我的全局。问题肯定与使用全局变量有关。尝试进行双重获取和双重释放,也许会奏效?
  • 使用双重获取和双重释放启动了一个无限循环。
  • 没关系,弄清楚为什么我得到了奇怪的结果......我在加入所有线程之前不小心写了 print(wins+loss) 段代码。
  • @ToastyEngineer 哎呀,我什至没看到那部分
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 2022-01-27
  • 2018-05-09
  • 2019-10-15
  • 1970-01-01
  • 2020-04-13
相关资源
最近更新 更多