C++ pThread 程序未运行完成

标签 c++ linux multithreading pthreads cygwin

<分区>

我遇到了一个奇怪的问题,我的 C++ 多线程程序没有运行完成。它应该运行 NUM_THREADS - 1 次。任何帮助我指明正确方向的资源都将不胜感激! 目前主要有这些功能

int main(void) {
int ret;
//Threads + current thread tracker
pthread_t threads[NUM_THREADS]; int j = 0;
int num_transacts = 0;  bool isBuy = true;

srand(time(NULL));
Stock MSFT("MSFT"); stocks.push_back(MSFT);
Stock AMZN("AMZN"); stocks.push_back(AMZN);
Stock BAC("BAC"); stocks.push_back(BAC);
Stock NKE("NKE"); stocks.push_back(NKE);

//Buys or Sells for NUM_THREADS - 1 times
while (num_transacts < NUM_THREADS) {
    if (isBuy) {
        //Percent chance to buy
        if (((double)rand() / (double)RAND_MAX) < Z) {
            cout << "Making buy thread.\n";
            pthread_mutex_lock(&mLock);

            ret = pthread_create(&threads[j], NULL, buy, NULL);
            if (ret != 0) {
                cout << "Thread failed at Buy Thread Create.\n";
            }

            pthread_mutex_unlock(&mLock);
            cout << "BuyNumTrans: " << num_transacts << "\n";

            ++j;
            ++num_transacts;
            isBuy = false;
        }
    }
    else {
        if (bought.size() > 0) {
            //Percent chance to sell if it has increased or decreased too much in price
            int s = rand() % bought.size();
            if ((bought.at(s).checkPrice()) > (((1 + X)*bought.at(s).getCost())) || (bought.at(s).checkPrice()) < (((1 + Y)*bought.at(s).getCost()))) {
                cout << "Making sell thread.\n";

                pthread_mutex_lock(&mLock);
                ret = pthread_create(&threads[j], NULL, sell, (void*) &s);
                if (ret != 0) {
                    cout << "Thread failed at Sell Thread Create.\n";
                }

                pthread_mutex_unlock(&mLock);
                cout << "SellNumTrans: " << num_transacts << "\n";

                ++j;
                ++num_transacts;
            }
            //Gets a new price possibility
            bought.at(s).getPrice();
        }
        isBuy = true;
    }
}

for (int i = 0; i < NUM_THREADS; ++i) {
    pthread_join(threads[i], NULL);
}

return 0;
}

pthread_mutex_t mLock;
pthread_mutex_t bLock;
pthread_mutex_t sLock;
vector<Stock> stocks;
vector<Stock> bought;
int balance = 1000000, yield = 0, profit = 0, Tcost = 0;

//In format  BUY MSFT 100 35.2
//In format  SELL MSFT 80 45
void* processTransact(void* argument) {
    string* arg = (string*)argument;
    istringstream iss(*arg);
    vector<string> words{ istream_iterator<string>(iss), istream_iterator<string> {} };

    if (words.front() == "BUY") {
        words.erase(words.begin());

        //gets the symbol name
        string symbol = words.front();
        words.erase(words.begin());

        //gets num of stocks to buy
        string a = words.front();
        int buyNum = atoi(a.c_str());
        words.erase(words.begin());

        //gets the price per share
        a = words.front();
        int sharePrice = atoi(a.c_str());

        //update num_shares, cost, balance, and Tcost
        Stock newBuy(symbol, buyNum, sharePrice);

        balance -= (buyNum * sharePrice);
        bought.push_back(newBuy);

        cout << "Bought stock... " << balance << endl;

        pthread_exit(NULL);
    }
    else {
        words.erase(words.begin());

        //gets the symbol name
        string symbol = words.front();
        words.erase(words.begin());

        //gets num of stocks to sell
        string a = words.front();
        int buyNum = atoi(a.c_str());
        words.erase(words.begin());

        //gets the price per share
        a = words.front();
        int sharePrice = atoi(a.c_str());

        a = words.front();
        int s = atoi(a.c_str());

        //update num_shares, cost, balance, and Tcost
        balance += (buyNum * sharePrice);
        bought.erase(bought.begin() + s);

        cout << "Sold stock... " << balance << endl;

        pthread_exit(NULL);
    }

    sleep(2);
}

void* buy(void*) {
    pthread_mutex_lock(&mLock);
    pthread_t thread;
    srand(time(NULL));
    int ret;
    int i = rand() % stocks.size();

    //Creates a string that processTransact can parse
    string transactString = "BUY " + stocks.at(i).getName() + " 100 " + to_string(stocks.at(i).getPrice());//make transaction string

    ret = pthread_create(&thread, NULL, processTransact, (void*)&transactString);
    if (ret != 0) {
        cout << "Error in buy thread process create.\n";
    }

    pthread_join(thread, NULL);
    pthread_mutex_unlock(&mLock);
    pthread_exit(NULL);
}

void* sell(void* argument) {
    pthread_mutex_lock(&mLock);
    pthread_t thread;
    int ret, s = *((int*)argument);;

    //Creates a string that processTransact can parse
    string transactString = "SELL " + bought.at(s).getName() + " 100 " + to_string(bought.at(s).getPrice()) + to_string(s);//make transaction string

    ret = pthread_create(&thread, NULL, processTransact, (void*)&transactString);
    if (ret != 0) {
        cout << "Error in sell thread process create.\n";
    }

    pthread_join(thread, NULL);
    pthread_mutex_unlock(&mLock);
    pthread_exit(NULL);
}

最佳答案

在上面的代码中,我看到在bought 变量访问期间存在潜在的未定义行为问题。这可能是您遇到问题的原因。

while 循环中有几行:

if (bought.size() > 0) {
  //Percent chance to sell if it has increased or decreased too much in price
  int s = rand() % bought.size();

void* processTransact(void* argument) 函数中:

bought.push_back(newBuy);
// Code skipped ....  
bought.erase(bought.begin() + s);

来自 processTransact 的代码在单独的线程中修改 bought 的大小。在 while 循环中,对 bought.size() 的访问与 mLock 互斥锁的使用不同步。这意味着您可能会在 bought.size() > 0 验证后得到空的 bought vector 。它在 rand() % 0 处导致未定义的行为。

此外,C++ 标准不保证 thread safety当同一个容器(bought)被不同的线程修改和读取时。

关于C++ pThread 程序未运行完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40823178/

相关文章:

c++ - 在 C++ 中以优雅的方式计时

c++ - 传递函数到动态链接库

objective-c - 原始值类型属性的线程安全 - Objective C

python - 从 QThread 生成并插入到 QTreeWidget 中的 QWidget 的正确父子关系

.net - NAnt 和双平台构建 - 在 Windows 和 Mono/Linux 上构建的最佳方式

c++ - 为什么 ZeroMQ 不使用其内部线程等待(接收/发送)?

c++ - 选择哪种设计来进行复杂的对象初始化?

c++ - multimap 和无序图的区别

linux - 无法使用 Flash Media Live Encoder 连接到 Linux VPS CentOS 服务器上的 Flash Media 服务器

linux - 在 Bash 中将文本文件作为命令运行