我正在用C ++编写多线程合并排序。上下文:用户使用适当的标志(例如, “ ./mergeSort 100 -t 20”
第一个数字代表程序应生成和排序的随机数,-t标志代表使用线程,最后一个数字代表程序应使用的最大线程数(当程序达到最大数量时)。线程,它继续执行标准的合并排序,而无需多线程)。
为了计算线程数,我使用了具有互斥锁的全局变量number_of_units,但是我一生都无法正确使用它。
标准合并排序功能将打印文本“标准”,而线程功能将打印出“新线程#”,其中#是程序仍可以创建的新线程数。每次启动新线程时,我都会递减计数器。这是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);
}
}
和标准mergeSort:
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
问题在于计数器达到零后正在创建新线程...有人知道如何停止该线程吗?我假设这只是互斥锁的位置...
答案 0 :(得分:1)
您没有将互斥锁锁定在修改或阅读*number_of_units
的位置。锁定这些用法。
即使互斥锁被锁定在这些变量访问的周围,您也需要确保在读取和修改之间没有其他线程尝试读取。您可以按住锁直到两个都完成。
您还应该使用std::lock_guard
或std::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>
。