我有一個我想從多個線程訪問和使用的向量。我在下面創建了一個示例來說明我想完成的功能。從多個線程訪問和使用std :: vector
目標是(1)高速度,(2)線程安全,和(3)如果可能的話繼續使用向量,因爲我的大型項目使用矢量遍佈整個地方,因此我想保持這一點。
但是,如果我需要從矢量切換到其他東西,那麼我對此也是開放的。
下面的例子編譯但相當快速崩潰,因爲它不是線程安全的。
關於如何修復以下示例的任何想法,我可以將其應用於我的大型項目?
謝謝:
#include <vector>
#include <ctime>
#include <thread>
#include <iostream>
#include <random>
#include <atomic>
#include <algorithm>
enum EmployeeType {
HOURLY = 0,
SALARIED = 1,
COMMISSION = 2,
OTHER = 3
};
enum EmployeePosition {
SalesPerson = 0,
Cashier = 1,
Stocker = 2,
Janitor = 3,
AssistantManager = 4,
Manager = 5,
GeneralManager = 6,
Owner = 7
};
class Employee;
class Employee {
private:
float _TotalCostPerYear;
EmployeeType _TypeOfEmployee;
EmployeePosition _PositionOfEmployee;
protected:
public:
Employee() :_TotalCostPerYear(0.0f), _TypeOfEmployee(EmployeeType::HOURLY),
_PositionOfEmployee(EmployeePosition::SalesPerson){};
float GetTotalCost() { return _TotalCostPerYear; }
void SetTotalCost(float ValueToSet) { _TotalCostPerYear = ValueToSet; }
EmployeeType GetEmployeeType() { return _TypeOfEmployee; }
void SetEmployeeType(EmployeeType ValueToSet) { _TypeOfEmployee = ValueToSet; }
EmployeePosition GetEmployeePosition() { return _PositionOfEmployee; }
void SetEmployeePosition(EmployeePosition ValueToSet) { _PositionOfEmployee = ValueToSet; }
};
std::vector <Employee> AllEmployees;
std::thread* AddEmployeesThread;
std::thread* RemoveEmployeesThread;
std::thread* CalculateEmploymentCostsThread;
std::thread* PrintTotalsThread;
std::atomic<bool> ContinueProcessing = true;
std::atomic<float> TotalSalaryCosts = 0.0f;
std::uniform_int_distribution<int>* RandDistTypeOfEmployee;
std::uniform_int_distribution<int>* RandDistPositionOfEmployee;
std::uniform_real_distribution<float>* RandDistSalaryOfEmployee;
std::mt19937* RandomNumberGenerator;
time_t rawtime;
struct tm timeinfo;
void RandomAddEmployees();
void RandomRemoveEmployees();
void CalculateEmployementCosts();
void PrintTotals();
void RandomAddEmployees() {
while (ContinueProcessing) {
Employee NewEmployee;
NewEmployee.SetEmployeePosition((EmployeePosition)(*RandDistPositionOfEmployee)(*RandomNumberGenerator));
NewEmployee.SetEmployeeType((EmployeeType)(*RandDistTypeOfEmployee)(*RandomNumberGenerator));
NewEmployee.SetTotalCost((*RandDistSalaryOfEmployee)(*RandomNumberGenerator));
AllEmployees.push_back(NewEmployee);
}
}
void RandomRemoveEmployees() {
while (ContinueProcessing) {
EmployeePosition PositionToRemove = (EmployeePosition)(*RandDistPositionOfEmployee)(*RandomNumberGenerator);
static const auto is_position_erasable = [&PositionToRemove](Employee& E) { return E.GetEmployeePosition() == PositionToRemove; };
AllEmployees.erase(std::remove_if(AllEmployees.begin(), AllEmployees.end(), is_position_erasable), AllEmployees.end());
EmployeeType TypeToRemove = (EmployeeType)(*RandDistTypeOfEmployee)(*RandomNumberGenerator);
static const auto is_type_erasable = [&TypeToRemove](Employee& E) { return E.GetEmployeeType() == TypeToRemove; };
AllEmployees.erase(std::remove_if(AllEmployees.begin(), AllEmployees.end(), is_position_erasable), AllEmployees.end());
}
}
void CalculateEmployementCosts() {
while (ContinueProcessing) {
float RunningTotal = 0.0f;
for (unsigned int i = 0; i < AllEmployees.size(); ++i) {
RunningTotal += AllEmployees[i].GetTotalCost();
}
TotalSalaryCosts = RunningTotal;
}
}
void PrintTotals() {
while (ContinueProcessing) {
time(&rawtime);
localtime_s(&timeinfo, &rawtime);
if ((timeinfo.tm_sec % 5) == 0) {
std::cout << "\n\nIn total there are " << AllEmployees.size() << " employees with a total cost of " << TotalSalaryCosts << " to the company.";
}
}
}
int main(int argc, char** argv) {
time(&rawtime);
localtime_s(&timeinfo, &rawtime);
RandomNumberGenerator = new std::mt19937((unsigned int)timeinfo.tm_sec);
RandDistTypeOfEmployee = new std::uniform_int_distribution<int>(0, 3);
RandDistPositionOfEmployee = new std::uniform_int_distribution<int>(0, 7);
RandDistSalaryOfEmployee = new std::uniform_real_distribution<float>(35000.0f, 300000.0f);
std::cout << "Welcome to the crude employment simulation program. Press enter to get started.";
std::cout << "\n\nNote that once the program starts you can press any key to stop the simulation.\n";
std::cin.get();
AddEmployeesThread = new std::thread(RandomAddEmployees);
RemoveEmployeesThread = new std::thread(RandomRemoveEmployees);
CalculateEmploymentCostsThread = new std::thread(CalculateEmployementCosts);
PrintTotalsThread = new std::thread(PrintTotals);
std::cin.get();
std::cout << "\n\nExiting the simulation.";
ContinueProcessing = false;
AddEmployeesThread->join();
RemoveEmployeesThread->join();
CalculateEmploymentCostsThread->join();
PrintTotalsThread->join();
delete AddEmployeesThread;
delete RemoveEmployeesThread;
delete CalculateEmploymentCostsThread;
delete PrintTotalsThread;
delete RandDistSalaryOfEmployee;
delete RandDistPositionOfEmployee;
delete RandDistTypeOfEmployee;
}
你真的需要所有'新'嗎? – 2014-10-20 01:50:29
@NeilKirk可能不是;這是一個例子,我習慣於這樣使用C++。我可以把它們放到我的變量聲明部分,它應該可以工作。 – user3434662 2014-10-20 04:25:18