C++ - 无法弄清楚如何使用互斥锁计算线程数



我正在用C++编写一个多线程合并排序。上下文:用户使用适当的标志运行程序,例如"./mergeSort 100-t 20">

第一个数字代表程序应该生成和排序的随机数,-t标志代表使用线程,最后一个数字代表该程序应该使用的最大线程数(当程序达到最大线程数时,它将继续进行标准合并排序,而不使用多线程(。

为了计算线程的数量,我使用了一个带有互斥锁的全局变量number_of_ounits,但就我的一生而言,我无法做到这一点。

标准合并排序函数打印文本"标准",线程函数打印"新线程#",其中#是程序仍然可以创建的新线程数。每次启动新线程时,我都会递减计数器。下面是main((的一个块:

cout << "array: ";
printArray(nums);
cout << endl;
mergeSortDirector(sort, nums, 0, nums.size() - 1);
cout << endl << "sorted array: ";
printArray(nums);

mergeSortDirector最初只是将程序引导到正确的排序,在本例中为mergeSortThread:

void mergeSortThread(vector<int> &nums, int beg, int end) {
cout << "new thread " << *number_of_units << endl;
int mid;
thread half1;
thread half2;
if (beg < end) {
mid = (beg + end) / 2;
if(*number_of_units > 1) {
*number_of_units -= 2;
mtx.lock();
half1 = thread(mergeSortThread, std::ref(nums), beg, mid);
mtx.unlock();
mtx.lock();
half2 = thread(mergeSortThread, std::ref(nums), mid + 1, end);
mtx.unlock();
half1.join();
half2.join();
} else if(*number_of_units == 1) {
*number_of_units--;
mtx.lock();
half1 = thread(mergeSortThread, std::ref(nums), beg, mid);
mtx.unlock();
mergeSort(nums, mid + 1, end);
half1.join();
} else {
mergeSort(nums, beg, mid);
mergeSort(nums, mid + 1, end);
}
merge(nums, beg, mid, end);
}
}

和标准合并排序:

void mergeSort(vector<int> &nums, int beg, int end) {
cout << "standard" << endl;
int mid;
if (beg < end) {
mid = (beg + end) / 2;
mergeSort(nums, beg, mid);
mergeSort(nums, mid + 1, end);
merge(nums, beg, mid, end);
}
}

程序的输出(有15个随机数和最多10个线程(是:

array: 660919 974282 721803 971892 908195 137470 226270 609453 19612 988775 652618 298558 125993 598676 489395 
new thread 10
new thread 8
new thread 6
new thread 4
new thread 2
new thread 0
standard
standard
standard
standard
standard
standard
new thread 0
standard
standard
standard
standard
new thread 0
standard
standard
new thread 0
standard
standard
new thread 0
standard
standard
new thread 0
standard
standard
sorted array: 19612 125993 137470 226270 298558 489395 598676 609453 652618 660919 721803 908195 971892 974282 988775 

问题是在计数器达到零之后会生成新的线程。。。有人知道我该怎么阻止吗?我想这只是我对互斥锁的定位。。。

您没有在修改或读取*number_of_units的点附近锁定互斥对象。把锁锁在那些地方。

即使互斥锁在这些变量访问周围被锁定,您也需要确保在读取和修改之间没有其他线程尝试读取。你可以按住锁,直到两者都完成。

您还应该使用std::lock_guardstd::unique_lock,而不是直接锁定互斥对象。

std::unique_lock lock(mtx);
if(*number_of_units > 1) {
*number_of_units -= 2;
lock.unlock();
[...]
} else if(*number_of_units == 1) {
*number_of_units--;
lock.unlock();
[...]
} else {
lock.unlock();
[...]
}

如果您没有使用C++17,则需要为std::unique_lock指定互斥类型,例如std::unique_lock<std::mutex>

最新更新