C++ Getline 并不总是在 Linux 中的多个分叉进程中获取行

C++ Getline not always getting line in multiple forked processes in Linux

我正在尝试创建一个程序来创建多个进程,每个进程从控制台读取一行,然后用它做一些事情。我在使用 getline(cin, temp) 时遇到问题,只是有时会读一行。输入缓冲区已经加载了 4 行文本。

编辑:我需要使用 fork,它创建多个进程(而不是线程)以便使用 wait,它等待第一个子进程完成,然后继续。

#include <iostream>
#include <iostream>
#include <string>
#include <cstring>
#include <sstream>
#include <unistd.h>
#include <sys/wait.h>

using namespace std;

int childprog();

int main() 
{

    pid_t childpid;

    for (int i = 0; i < 4; ++i)
    {
        if ((childpid = fork()) == 0) //Child process
        {
            childprog();
            return 0;
        }
    }

    if (childpid != 0) //If Parent
    {
        wait(0);
        //Stuff
        return 0;
    }
}

int childprog()
{
    string temp;
    getline(cin, temp);
    cout << temp << endl; //Actually do other stuff, just here for debugging
    return 0;
}

虽然它应该打印出来:

string number one
string number two
string number three
string number four

打印出来:

string number one

string number two
string number three

(blank line)
string number one

string number two

在任何可能的位置都有空行。

感谢您的帮助!

问题是每个线程都在访问共享资源:getline 和输入缓冲区。有些操作是原子的,有些是可以中断的。

这意味着操作的确切时间可能会相互干扰。例如,两个线程检查接下来要读取的是哪一行,它们都被告知同一行。然后就是一个"race condition"看哪个线程先读,另一个线程得到一个空行。

您需要以某种方式锁定 getline,以便每个线程都可以在其他线程潜入并尝试获取一些数据之前读取一行。一个更好的解决方案是避免两个进程处理相同的数据,但假设你不能,那么你可以使用 Mutex。

http://www.thegeekstuff.com/2012/05/c-mutex-examples/

如何使用互斥量的精简示例:

#include<pthread.h>
#include<unistd.h>

pthread_mutex_t lock;

int childprog()
{
    // Put the mutex lock and unlock around the minimum amount of code    
    // which needs to be an "atomic operation". While "locked" other 
    // threads won't run this bit of code, so keep it brief. However, 
    // Locking and unlocking is itself an expensive operation, so you
    // should be careful to minimize the number of times it happens

    string temp;

    pthread_mutex_lock(&lock);
    getline(cin, temp);
    pthread_mutex_unlock(&lock);

    cout << temp << endl;

    return 0;
}

// the rest of your program here

但是请注意,还有一行需要在使用互斥量之前对其进行初始化

pthread_mutex_init(&lock, NULL)

链接示例使用的是 pthread create,而不是 fork

在@JasonLang 发布他的回答并通知我这是一个访问问题后,我找到了解决方案。我通过简单地将输入缓冲区的读取移动到 fork() 之前来纠正它,确保只有一个进程会尝试一次读取它。

我替换了这个:

for (int i = 0; i < 4; ++i)
{
    if ((childpid = fork()) == 0) //Child process
    {
        childprog();
        return 0;
    }
}

有了这个:

string temp;
for (int i = 0; i < 4; ++i)
{
    getline(cin, temp);
    if ((childpid = fork()) == 0) //Child process
    {
        childprog(temp);
        return 0;
    }
}

还有这个:

int childprog()
{
    string temp;
    getline(cin, temp);
    cout << temp << endl; //Actually do other stuff, just here for debugging
    return 0;
}

有了这个:

int childprog(string input)
{
    cout << input << endl; //Actually do other stuff, just here for debugging
    return 0;
}