首页 文章

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

提问于
浏览
0

我正在用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

问题是在计数器达到零之后正在制作新的线程......有人知道我该如何阻止它?我假设这只是我对互斥锁的定位......

1 回答

  • 2

    您没有锁定修改或读取 *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> .

相关问题