线程未正确结束:它忽略失败的循环条件
Threads doesn't end correctly: it ignores failing loop conditions
我正在研究一个小的战斗代码,试图学习在 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
语句,直到玩家 1 死了。
我本以为while
会因为条件而结束(player.ask_dead() != true)
应该失败。
有什么建议吗?
通过放置 mutext 来正确完成同步,以避免并发访问您的对象。这已经是一个非常好的开始了!
问题:
问题是,当您创建线程时,它会创建您传递的参数的私有副本(另请参阅此相关 SO 问题)
您可以通过在 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/C++:socket() 创建在循环中失败,打开的文件太多
- 谁能弄清楚为什么我的循环会失败?
- 断言失败:列出迭代器不可递增(不在循环中)
- 对于循环执行失败,因为变量我不会递增,为什么?
- GCC自动矢量化在减少循环中失败
- 密码检查程序-匹配密码失败-循环失败
- c++ 中带有容器迭代器的循环类型依赖关系(GCC 失败,而 MSVC 正常)
- 线程未正确结束:它忽略失败的循环条件
- 在循环中第二次调用luaT_pushudata时失败
- 在for循环内部使用setw是失败的
- 用于循环计数器失败的 C++
- 输入验证循环在第一次输入失败后无法正常工作
- std::vector push_back 在并行 for 循环中使用时失败
- 循环迭代后共享指针断言失败
- 对于循环不递增或循环不失败测试
- fgetwc EOF 循环测试失败,但 65535 正常
- 在字符串上循环以查看字符串失败的位置
- 当循环失败时,当读取int和字符串C++时
- 迭代器结束检查在“for”循环内递增后失败
- 编译不完整类型失败;循环依赖