gpt4 book ai didi

c++ - 线程未正确结束 : it ignores failing loop conditions

转载 作者:行者123 更新时间:2023-11-28 02:30:38 32 4
gpt4 key购买 nike

我正在编写一个小的战斗代码来尝试学习在 C++ 中使用线程,但偶然发现了一个我无法弄清楚的错误。

我使用互斥文本进行同步:

mutex mux1;

和一个线程函数:

void dueler(Player &player, Player &enemy)
{
do
{
Sleep(player.get_as());
mux1.lock();
cout << player.get_name()<< " hit " << enemy.get_name() << " for " << player.get_str() << " damage!" << endl;
enemy.dmg(player.get_str());
mux1.unlock();
} while ((enemy.ask_dead() != true) && (player.ask_dead() != true));
}

我在 main 中调用(完整代码:http://pastebin.com/1FBf2FCQ):

int main()
{
Player Player1("kasper", 100, 5, 200);
Player Player2("Bagger", 150, 8, 3000);
thread dueler1(dueler,Player1,Player2);
thread dueler2(dueler, Player2, Player1);
dueler1.join();
dueler2.join();
cout <<endl<< "battle is over!";
}

线程函数使玩家(http://pastebin.com/ZCTfUYiS)相互对抗:

class Player
{
public:
Player(string name_, int maxhp_, int strenght_, int attackspeed_) {
name = name_;
maxhp = maxhp_;
hp = maxhp;
strenght = strenght_;
attackspeed = attackspeed_;
isdead = false;
}
void fullhp() { hp = maxhp; }
void dmg(int dmg) {
hp -= dmg;
if (hp < 0) dead();
}
void dead() {
isdead = true;
cout << name <<" died like a pessant";
}
string get_name() { return name; }
int get_hp() { return hp; }
int get_maxhp() { return maxhp; }
int get_str() { return strenght; }
int get_as() { return attackspeed; }
bool ask_dead() {return isdead; }
private:
string name;
int maxhp;
int hp;
int strenght;
int attackspeed;
bool isdead;
};

问题发生在 Player2 被杀死时:

  • 线程 1(处理玩家 1 造成的伤害)按原样停止,
  • 线程 2(处理已死亡的 Player2)继续运行,并完全忽略 while 语句,直到 Player1 已死亡。

我本来希望 while 结束,因为条件 (player.ask_dead() != true) 应该失败。

有什么建议吗?

最佳答案

您已通过放置互斥体来正确完成同步,以避免并发访问您的对象。这已经是一个很好的开始了!

问题:

问题是当你创建一个线程时,它会为你传递的参数创建一个私有(private)拷贝(另请参见 this related SO question)

您可以通过在 dueller() 中添加以下第一条语句轻松地通过实验验证引用:

cout << "dueller with player " << (void*)&player << " and ennemy " << (void*)&enemy << endl;

dueler() 通过引用调用参数时,引用不是指向原始对象(main() 中的局部变量)而是指向它的克隆。

解决方案:

你必须使用 std::ref()确保所有线程都引用相同的对象:

thread dueler1(dueler, std::ref(Player1), std::ref(Player2));
thread dueler2(dueler, std::ref(Player2), std::ref(Player1));

其他备注:

当玩家死亡时,他的 dueler() 函数很可能正在等待互斥锁。因此,当互斥锁变得空闲时,他会造成损害,尽管他已经死了。

好的!在游戏中你可能会争辩说玩家已经死了但仍然拿着这把剑跑向受害者......但我们也可以通过在进入保护区时添加一个条件来解决它:

    mux1.lock();  // we were waiting, a certain time
if (!player.ask_dead()) { // so first check if we are still alive
cout << player.get_name() << " hit " << enemy.get_name() << " for " << player.get_str() << " damage!" << endl;
enemy.dmg(player.get_str());
}
mux1.unlock();

关于c++ - 线程未正确结束 : it ignores failing loop conditions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29106068/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com