【问题标题】:First steps with threading failed线程的第一步失败
【发布时间】:2020-07-24 14:48:51
【问题描述】:

嗨:请进一步找到我的代码。 我使用 mingw 和参数 -Wmain;-pedantic;-std=c++11;-Wall 编译。 Codelite 设置编译器选项之间的分号

这里我尝试学习如何使用线程和互斥锁:https://en.cppreference.com/w/cpp/thread/mutex

主模块在包含部分之后包含全局变量std::mutex mtx 线程函数在 ma​​in() 函数中声明和连接; friend class SL 的函数定义也可以在这里找到。类和方法定义分布在接下来的两个模块中。

这些是我无法处理的错误消息: 消息 1

C:/Program Files/CodeBlocks/MinGW/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/thread:240:2: error: no matching function for call to 'std::thread::_Invoker<std::tuple<void (*)(int, int, SL&), int, int, SL> >::_M_invoke(std::thread::_Invoker<std::tuple<void (*)(int, int, SL&), int, int, SL> >::_Indices)'
  operator()()
  ^~~~~~~~

消息 2

C:/Program Files/CodeBlocks/MinGW/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/thread:233:29: error: no matching function for call to '__invoke(std::__tuple_element_t<0, std::tuple<void (*)(int, int, SL&), int, int, SL> >, std::__tuple_element_t<1, std::tuple<void (*)(int, int, SL&), int, int, SL> >, std::__tuple_element_t<2, std::tuple<void (*)(int, int, SL&), int, int, SL> >, std::__tuple_element_t<3, std::tuple<void (*)(int, int, SL&), int, int, SL> >)'
    -> decltype(std::__invoke(_S_declval<_Ind>()...))
     __invoke(_Callable&& __fn, _Args&&... __args)
     ^~~~~~~~

*Message 2 似乎引用了某种类型的移动构造函数...

我认为朋友功能是造成困境的原因,但无法验证

请帮忙。

主模块

#include <mutex>
#include <thread>
#include "sl.h"
std::mutex mtx;

void play(int die1, int die2, SL& p){
  std::this_thread::sleep_for(std::chrono::seconds(1));
  mtx.lock();
  if (p.dice.size() > 0) {
    p.dice.resize(0);
    }
  p.set_dice(die1, die2);
  rollDice(p);
  mtx.unlock();
  }

void rollDice(SL& p) {
  int iFound = -1;
  int iAdd = p.dice[0] + p.dice[1];
  p.addPosition(iAdd);
  p.bounceBack();
  if (p.position == 100) {
    printResult(p, iFound);
    std::cout << "Game over" << std::endl;
    return;
    }
  if ((iFound = p.check(SL::ladders, p.position)) != -1) {
      p.setPosition(SL::ladders[iFound].second);
      iFound += 100;
      }
  else if ((iFound = p.check(SL::snakes, p.position)) != -1) {
      p.setPosition(SL::snakes[iFound].second);
      }// snakes, position + iAdd
  printResult(p, iFound);
  if (p.dice[0] == p.dice[1]) {
    mtx.unlock();
    play(rand() %6 + 1, rand() % 6 + 1, p);
    }
  }

void printResult(SL& p, int iFound) {
  std::cout << ++p.iTimes << ") "
            << p.get_name() << "<<<< "
            << p.dice[0] << "|"
            << p.dice[1] << " position: "
            << p.position;

  if (iFound != -1) {
    if (iFound > 100) { // this is a ladder field
      iFound -= 100;
      std::cout << " LADDER from "
                << SL::ladders[iFound].first << "|"
                << SL::ladders[iFound].second;
        }
    else {
      std::cout << " SNAKE from "
                << SL::snakes[iFound].first  << "|"
                << SL::snakes[iFound].second;
        }
      }
    std::cout << std::endl;
    }

int main()
  {
  srand(time(NULL));
  SL one("Player 1"),
                two("Player 2");
  std::thread t1 (play, rand() %6 + 1, rand() %6 + 1, one);
  std::thread t2 (play, rand() %6 + 1, rand() %6 + 1, two);
  while((one.get_position() != 100) && (two.get_position() != 100)) {
    t1.join();

    t2.join();
    }
  return 0;
  }

// 类声明

#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <ctime>
#include <iomanip>

class SL {
  public:
  SL(const std::string& strName) : player(strName), position(0), iTimes(0) {}
  ~SL() = default;

  private:
    friend void play(int die1, int die2, SL& p);
    friend void rollDice(SL&);
    friend void printResult(SL&, int);
    static const std::pair<int, int> snakes[];
    static const std::pair<int, int> ladders[];
    std::string player;
    int position;
    int iTimes;
    std::vector<int> dice;
  protected:
    int check(const std::pair<int, int> field[], const int iField);
  public:
    void addPosition(const int iPosition);
    void setPosition(const int iPosition);
    void bounceBack();
    void set_dice(int die1, int die2);
    const int get_position() const;
    const std::string& get_name() const;
    const std::vector<int> get_dice() const;
    };
// friend function
void play(int die1, int die2, SL& p);
void rollDice(SL&);
void printResult(SL&, int =-1);

// 类方法 - 静态变量

#include <mutex>
#include <thread>
#include "sl.h"

inline void SL::addPosition(const int iPosition) {
  position += iPosition;
  }
inline void SL::setPosition(const int iPosition) {
  position = iPosition;
  }
inline void SL::bounceBack() {
  if (position > 100) {
    int iBounceBack = position - 100;
    position -= iBounceBack;
    }
  }
inline void SL::set_dice(int die1, int die2){
  if (dice.size() > 0) {
    dice.erase(dice.begin(), dice.end());
    }
  dice.push_back(die1);
  dice.push_back(die2);
  }
const int SL::get_position() const {return position;}
const std::string& SL::get_name() const {return player;}
const std::vector<int> SL::get_dice() const {return dice;}

int SL::check(const std::pair<int, int> field[], const int iField) {
  const int end = 10;
  int result = -1;
  for ( size_t idx = 0; idx < end; idx++) {
    if (field[idx].first == iField){
      result = idx;
      break;
      }
    else if (iField > field[idx].first)
      break;
    }
  return result;
}

const std::pair<int, int> SL::ladders[] {
      std::make_pair( 2, 38),
      std::make_pair( 7, 14),
      std::make_pair( 8, 31),
      std::make_pair(15, 26),
      std::make_pair(28, 84),
      std::make_pair(36, 44),
      std::make_pair(51, 67),
      std::make_pair(71, 91),
      std::make_pair(78, 98),
      std::make_pair(87, 94)
      };

const std::pair<int, int> SL::snakes[] {
      std::make_pair(16,  6),
      std::make_pair(46, 25),
      std::make_pair(49, 11),
      std::make_pair(62, 19),
      std::make_pair(64, 60),
      std::make_pair(74, 53),
      std::make_pair(89, 68),
      std::make_pair(92, 88),
      std::make_pair(95, 75),
      std::make_pair(99, 80)
      };

【问题讨论】:

  • 有一些代码,但这是以防万一有人想编译它并可能看到错误消息。所有线程项目都可以在 main 和 play, function 中找到,它们位于 main 模块中。谢谢。
  • std::thread 默认情况下将按值传递参数,而您的 play 函数通过引用接受其第三个参数 -- SL &amp;。尝试std::thread t1 (play, rand() %6 + 1, rand() %6 + 1, std::ref(one)); 并同样尝试其他线程。在某处有一个骗局。目前找不到。
  • 嗨,G.M.我试图这样做。我的 main() 现在看起来像这样:int main() { srand(time(NULL)); SL one("Player 1"), two("Player 2"); int die1 = rand() %6 + 1; int die2 = rand() %6 + 1; std::thread t1 (play, die1, die2, std::ref(one)); std::thread t2 (play, die1, die2, std::ref(two)); while((one.get_position() != 100) &amp;&amp; (two.get_position() != 100)) { t1.join(); t2.join(); } return 0; } 它仍然对我不起作用。

标签: c++ multithreading c++11 mutex


【解决方案1】:

我试图接受 G.M. 的建议,但我真的无法做到。 对于多线程初学者来说,这是一个不错的选择:

https://hackernoon.com/learn-c-multi-threading-in-5-minutes-8b881c92941f

阅读完所有这些后,我决定使用主模块中的 mutex mtx 全局变量来使用 std::lock 保护:

void play(int die1, int die2, SL& p){
  std::lock_guard<std::mutex> guard(mtx);
  if (p.dice.size() > 0) {
    p.dice.resize(0);
    }
  p.setDice(die1, die2);
  int iGameOver = 0;
  rollDice(p, iGameOver);
  if (iGameOver)
    return;
  }

在 rollDice 函数中,我曾经通过 play 递归调用 rollDice 函数。这个配置导致了死锁,我摆脱了那个逻辑并将递归替换为 main 内的两个循环。

int main()
  {
  srand(time(NULL));
  SL one("Player 1"),
     two("Player 2");
  while((one.getPosition() != 100) && (two.getPosition() != 100)) {
    int die1 = 0,
        die2 = 0;
    if (!two.gameOver()) {
      do {
        die1 = rand() % 6 + 1;
        die2 = rand() % 6 + 1;
        play(die1, die2, one);
        }while(die1 == die2);
      std::cout << "-----------------" << std::endl;
      }
    if (!one.gameOver()) {
      do {
        die1 = rand() % 6 + 1;
        die2 = rand() % 6 + 1;
        play(die1, die2, two);
        }while(die1 == die2);
      std::cout << "-----------------" << std::endl;
      }
    }
  return 0;
  }

从 rollDice 中通过 play 再次调用 rollDice() 的相应逻辑已从 rollDice 函数中移除,现在看起来像这样。

void rollDice(SL& p, int& gameOver) {
  int iFound = -1;
  int iAdd = p.getAdded();
  p.addPosition(iAdd);
  p.bounceBack();
  if (p.getPosition() == 100)
    p.setGameOver();
  if (p.gameOver()) {
    printResult(p, iFound);
    std::cout << "Game over" << std::endl;
    return;
    }
  if ((iFound = p.check(SL::ladders, p.getPosition())) != -1) {
      p.setPosition(SL::ladders[iFound].second);
      iFound += 100;
      }
  else if ((iFound = p.check(SL::snakes, p.getPosition())) != -1) {
      p.setPosition(SL::snakes[iFound].second);
      }// snakes, position + iAdd
  printResult(p, iFound);
  }

我不太确定,我原来的方法哪里出了问题,但是我的第一个多线程测试代码已经成功实现,如果没有我发布并得到 G.M.s 的建议,它就不会发生。谢谢。

【讨论】:

    猜你喜欢
    • 2016-04-05
    • 1970-01-01
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    相关资源
    最近更新 更多