Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 处理两个线程,一个正在休眠,另一个正在等待输入_C_Multithreading_Pthreads - Fatal编程技术网

C 处理两个线程,一个正在休眠,另一个正在等待输入

C 处理两个线程,一个正在休眠,另一个正在等待输入,c,multithreading,pthreads,C,Multithreading,Pthreads,问题:创建一个接受用户输入但在几秒钟后超时的程序(假设现在是2秒钟) 方法:我创建了两个线程,一个线程等待用户输入(inputThread使用tid[0]),另一个线程睡眠2秒钟(sleepThread使用tid[1])。我从另一个线程的例程中取消一个线程,如下所示: #include <stdio.h> #include <unistd.h> #include <pthread.h> pthread_t tid[2]; void* inputThread

问题:创建一个接受用户输入但在几秒钟后超时的程序(假设现在是2秒钟)

方法:我创建了两个线程,一个线程等待用户输入(
inputThread
使用
tid[0]
),另一个线程睡眠2秒钟(
sleepThread
使用
tid[1]
)。我从另一个线程的例程中取消一个线程,如下所示:

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

pthread_t tid[2];

void* inputThread()
{   
    int n;
    printf("Enter number:");

    // wait for input; if input is given then go ahead and cancel the sleeper thread.
    scanf("%d",&n); 

    // cancel the sleeper thread
    pthread_cancel(tid[1]); 

    printf("Got value:%d\n",n);
}

void* sleepThread()
{
    // sleep for 2 seconds and cancel the input thread.
    sleep(2); 

    // cancel the input thread
    pthread_cancel(tid[0]); 

    printf("\nNo value entered!\n");
}

int main(int argc, char const *argv[])
{
    int r1,r2,r3,r4;

    // input taking thread 
    r1 = pthread_create(&tid[0],NULL,inputThread,NULL); 

    // sleeping thread
    r2 = pthread_create(&tid[1],NULL,sleepThread,NULL);

    r3 = pthread_join(tid[0],NULL);
    r4 = pthread_join(tid[1],NULL);

    return 0;
}
#包括
#包括
#包括
pthread_t tid[2];
void*inputThread()
{   
int n;
printf(“输入编号:”);
//等待输入;如果输入已给出,则继续并取消休眠线程。
scanf(“%d”和“&n”);
//取消枕木线
pthread_cancel(tid[1]);
printf(“获取值:%d\n”,n);
}
void*sleepThread()
{
//睡眠2秒钟并取消输入线程。
睡眠(2);
//取消输入线程
pthread_cancel(tid[0]);
printf(“\n未输入值!\n”);
}
int main(int argc,char const*argv[]
{
int r1、r2、r3、r4;
//输入获取线程
r1=pthread_create(&tid[0],NULL,inputThread,NULL);
//睡线
r2=pthread_create(&tid[1],NULL,sleepThread,NULL);
r3=pthread_join(tid[0],NULL);
r4=pthread_join(tid[1],NULL);
返回0;
}
到目前为止,该计划按预期运行

但是我的朋友说它不能保证工作,因为它取决于线程的调度方式。他试着向我解释,但我听不懂。他还说,
pthread\u cancel
只是一个取消线程的请求,它可能不会成功


因此,请有人指出潜在的错误和最佳做法,以避免同样的情况。为保证程序正常运行所做的任何更改也将受到赞赏。

您的朋友关于
pthread\u cancel
是取消线程的请求,可能不会总是成功

关于日程安排的部分,你需要提供他有哪些论点

为了解决您的问题,您可以放弃同时使用线程(除非这是您的任务的要求),而使用

这将使解决方案不可移植(仅符合POSIX),但
pthreads
无论如何也不可移植

select
允许您等待文件描述符(在本例中为
0
)以获取可用于读取的数据。它还允许您设置超时

fd_set set;
FD_ZERO(&set);
FD_SET(0, &set);

struct timeval timeout;
timeout.tv_sec = 2;
timeout.tv_usec = 0;

int ret = select(1, &set, NULL, NULL, &timeout);

if (ret == 1) {
    char buffer[20];
    int n;
    read(0, buffer, 20);
    sscanf(buffer, "%d", &n);
    printf("Got value:%d\n",n);
} else {
    printf("Time out\n");
}
该函数调用线程上的线程取消处理程序,这些处理程序返回后将调用线程的析构函数,析构函数反过来将终止线程

因为它是一个请求,所以可能会失败,这由
pthread\u cancel
返回一个非零整数表示


如果您使用两个以上的线程来执行此操作,或者在同一进程中有多个线程正在访问stdin,您可能会让线程等待访问stdin,从而导致所需的行为延迟。

您的朋友是对的,我认为他的意思是,您不能假定知道哪个线程首先运行/完成。 但两个线程都将被调度,因此thread1有时间请求用户输入并等待一点输入

我看不出有什么大问题,如果可以的话,就不要太担心


但是,您可以使用SIGALRM信号来代替
sleep
,但它涉及掩码,需要花费更多的时间来理解(我正在做的是:检查
task2
函数及其使用的掩码,如果您需要示例)。

只有一个线程正在访问
stdin
。您可以建议使用
pthread\u cancel
的任何替代方法吗?@RahulBharadwaj是的,您可以使用,它作为void的返回类型,永不失败。@JoshWeinstein
pthread\u exit
,终止调用线程。因此,必须从等待的线程调用它,这是不可能的。没有可靠的方法可以从另一个线程杀死一个线程。感谢您提供的解决方案。使用线程不是必需的,但我们使用线程只是为了学习线程库。如果只使用线程,我如何处理它?只有一个线程可以吗?@RahulBharadwaj我给出的解决方案是使用一个线程。如果你想使用多个线程,正确的方法是有一个睡眠线程(就像你现在拥有的那样)。超时后,它将
volatile
标志设置为0。主线程将
stdin
(0)fd设置为非阻塞模式,并继续尝试读取(适当的睡眠时间为10毫秒)。每次重复之前,它都会检查volatile变量。这样你可以得到同样的行为。好的,我理解。我将尝试使用
main
thread之外的一个额外线程来实现。@RahulBharadwaj您可以了解如何将0fd设置为非阻塞模式。虽然我会建议,fd先看,然后再看。如果将0 fd设置为非阻塞,我不确定标准库代码(如scanf、gets)的行为。如果用户不按enter键,则显示的代码不会超时。我使用了
sigprocmask
信号
。从来没有想过,我会尝试使用它来实现它,谢谢!