在C++中`for`循环的条件语句中使用右值

问题描述 投票:0回答:1

我正在执行一项编程任务,该任务接受

n
值并使用三个线程打印 zeroevenodd 数字。

例如,如果

n = 3
,则会打印
010203
。我遇到了一个奇怪的行为,当在 for 循环的条件检查中使用右值时,我的程序完全挂起而不执行任何操作。这种现象只出现在多线程程序中。因此,我将整个代码放在这里:

#include <functional>  // function
#include <iostream>
#include <mutex>   // mutex
#include <thread>  // thread

using namespace std;

class ZeroEvenOdd {
  private:
    int n;
    mutex zero_mtx, even_mtx, odd_mtx;

  public:
    ZeroEvenOdd(int n) {
        this->n = n;
        zero_mtx.unlock();

        even_mtx.lock();
        odd_mtx.lock();
    }

    // printNumber(x) outputs "x", where x is an integer.
    void zero(function<void(int)> printNumber) {
        for (int i = 1; i <= this->n; ++i) {
            zero_mtx.lock();

            printNumber(0);

            if (i & 1) {  // odd
                odd_mtx.unlock();

            } else {  // even
                even_mtx.unlock();
            }
        }
    }

    void even(function<void(int)> printNumber) {
        for (int a = 2; a <= ((this->n) + 1); a += 2) { // NOTE: `(this->n) + 1` is an rvalue
            even_mtx.lock();

            printNumber(a);

            zero_mtx.unlock();
        }
    }

    void odd(function<void(int)> printNumber) {
        for (int b = 1; b <= ((this->n) + 1); b += 2) { // NOTE: `(this->n) + 1` is an rvalue
            odd_mtx.lock();

            printNumber(b);

            zero_mtx.unlock();
        }
    }
};

// g++ 1116.cpp -std=c++11 -pthread -O0 && ./a.out
int main() {
    printf("helloworld\n");

    ZeroEvenOdd zod(3);

    auto printNumber = [](int x) { cout << x; };

    thread threadA([&]() { zod.zero(printNumber); });
    thread threadB([&]() { zod.even(printNumber); });
    thread threadC([&]() { zod.odd(printNumber); });

    threadA.join();
    threadB.join();
    threadC.join();

    return 0;
}

上面的程序可以用

g++ 1116.cpp -std=c++11 -pthread -O0 && ./a.out
编译并运行,但是程序只是挂起而不做任何事情。但是,如果我改变线路

for (int a = 2; a <= ((this->n) + 1); a += 2) { // NOTE: `(this->n) + 1` is an rvalue
for (int b = 1; b <= ((this->n) + 1); b += 2) { // NOTE: `(this->n) + 1` is an rvalue

for (int a = 2; a <= ((this->n) + 0); a += 2) {
for (int b = 1; b <= ((this->n) + 0); b += 2) {

然后一切都按预期进行

我尝试在单线程程序中重现这种现象,但这种行为在单线程程序中不存在。

我不确定这种行为是否与多线程有关。我只是提供我所拥有的所有证据供人们调查。

更新: 将拼写错误

lvalue
更改为
rvalue

c++ multithreading for-loop mutex rvalue
1个回答
0
投票

虽然不同线程中互斥体的锁定和解锁是an问题,但它不是the问题。

当循环控制为<= ((this->n)+1)时,程序进行如下:

  1. 父级锁定偶数并锁定奇数;
  2. threadB 等待均匀;
  3. threadC 等待奇数;
  4. threadA 锁定零,发出“0”,解锁奇数并等待零;
  5. threadC 锁定奇数,发出“1”,解锁零并等待零;
  6. threadA 锁定零,发出“0”,解锁偶数并等待零;
  7. threadB 锁定偶数,发出“2”,解锁零并等待偶数;
  8. threadA 锁定零,发出“0”,解锁零并退出;
  9. threadC 锁定奇数,发出“3”,解锁零并退出。

threadB 永远不会退出并永远等待,因为 (a += 2) == 4 且 ((this->n) + 1) == 4。

不会发出任何内容,因为输出仍处于缓冲状态。

© www.soinside.com 2019 - 2024. All rights reserved.