简体   繁体   English

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

[英]C++ - can't figure out how to count threads with mutex

I'm coding a multithreaded merge sort in C++. 我正在用C ++编写多线程合并排序。 Context: user runs the program with appropriate flags, eg "./mergeSort 100 -t 20" 上下文:用户使用适当的标志运行程序,例如“ ./mergeSort 100 -t 20”

The first number stands for how many random numbers should the program generate and sort, the -t flag stands for using threads and the last number stands for maximum number of threads the program should use (when the program reaches the maximum amount of threads, it continues with the standard merge sort without multi threading). 第一个数字表示程序应生成和排序的随机数,-t标志表示使用线程,最后一个数字表示程序应使用的最大线程数(当程序达到最大线程数时,它继续执行标准的合并排序,而不使用多线程)。

For counting the number of threads I use a global variable number_of_units with the mutex lock, but I just can't, for the life of me, get it right. 为了计算线程数,我使用了具有互斥锁的全局变量number_of_units,但是我一生都无法正确地做到这一点。

The standard merge sort function prints text "standard" and the threaded function prints out "new thread #" with # being the number of new threads that the program can still create. 标准合并排序功能将打印文本“标准”,而线程功能将打印出“新线程#”,其中#是程序仍可以创建的新线程数。 I decrement the counter everytime I start a new thread. 每次启动新线程时,我都会递减计数器。 Here is a block of main(): 这是main()的一个块:

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

the mergeSortDirector just directs the program to the correct sort initially, in this case to the mergeSortThread: 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);
    }
}

and the standard mergeSort: 和标准的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);
    }
}

The output of the program (with 15 random numbers and maximum 10 threads) is: 程序的输出(具有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 

The problem is that new threads are being made after the counter reaches zero... Does anybody know how can I stop that? 问题是计数器达到零后正在创建新线程。有人知道我该如何停止? I'm assuming it's just my positioning of the mutex locks... 我假设这只是互斥锁的位置...

You are not locking the mutex around the point where you modify or read *number_of_units . 您不会在修改或读取*number_of_units的点周围锁定互斥体。 Put the locks around those usages. 围绕这些用法设置锁。

Even if the mutex was locked around these variable accesses, you need to make sure that between the read and modification no other thread tries to read. 即使互斥锁被锁定在这些变量访问的周围,您也需要确保在读取和修改之间没有其他线程尝试读取。 You can do this by holding the lock until both are done. 您可以通过按住锁直到两个都完成来完成此操作。

You should also use std::lock_guard or std::unique_lock instead of locking the mutex directly. 您还应该使用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();
    [...]
}

If you are not using C++17, you will need to specify the mutex type for std::unique_lock , eg std::unique_lock<std::mutex> . 如果未使用C ++ 17,则需要为std::unique_lock指定互斥锁类型,例如std::unique_lock<std::mutex>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM