我遇到一个奇怪的问题,我的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);
}
答案 0 :(得分:1)
在上面的代码中,我在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
验证后您可能会获得空的bought.size() > 0
向量。它会导致rand() % 0
处的未定义行为。
此外,当从不同的线程修改和读取相同的容器(bought
)时,C ++标准不保证thread safety。