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++ 即使使用睡眠,线程也不会放弃CPU时间_C++_Multithreading_Signals - Fatal编程技术网

C++ 即使使用睡眠,线程也不会放弃CPU时间

C++ 即使使用睡眠,线程也不会放弃CPU时间,c++,multithreading,signals,C++,Multithreading,Signals,我正在运行这个程序,我有多个线程。三个线程正在为同一父进程生成信号。有四个处理程序线程用于处理信号生成线程生成的信号。我有一个监控线程,它也接收信号并根据需要进行处理。然而,我有一个情况。我可以看出,信号并不是平均分配的。我的意思是这些信号都指向同一个进程。我有四个处理程序线程和一个监视线程等待信号。这样他们中的任何人都可以接收到信号。我希望它能均匀分布。然而,我可以看到,在处理程序线程接收到整个突发信号的时候。下一次监视器线程处理整个突发信号时。为什么不统一呢。在处理程序/监视器线程完成处理一

我正在运行这个程序,我有多个线程。三个线程正在为同一父进程生成信号。有四个处理程序线程用于处理信号生成线程生成的信号。我有一个监控线程,它也接收信号并根据需要进行处理。然而,我有一个情况。我可以看出,信号并不是平均分配的。我的意思是这些信号都指向同一个进程。我有四个处理程序线程和一个监视线程等待信号。这样他们中的任何人都可以接收到信号。我希望它能均匀分布。然而,我可以看到,在处理程序线程接收到整个突发信号的时候。下一次监视器线程处理整个突发信号时。为什么不统一呢。在处理程序/监视器线程完成处理一个信号后,我添加了一个睡眠调用。因此,一旦处理器/监视器完成一个信号,它就应该给另一个机会来处理下一个信号。但是,输出没有显示这种情况

#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <signal.h>
#include <cstdio>
#include <stdlib.h>

#define NUM_SENDER_PROCESSES 3
#define NUM_HANDLER_PROCESSES 4
#define NUM_SIGNAL_REPORT 10
#define MAX_SIGNAL_COUNT 100000


using namespace std;

volatile int usrsig1_handler_count = 0;
int usrsig2_handler_count = 0;
int usrsig1_sender_count = 0;
int usrsig2_sender_count = 0;
int monitor_count = 0;
int usrsig1_monitor_count = 0;
int usrsig2_monitor_count = 0;
double time_1[10];
double time_2[10];
int lock_1 = 0;
int lock_2 = 0;
int lock_3 = 0;
int lock_4 = 0;
int lock_5 = 0;


double timestamp() {
  struct timeval tp;
  gettimeofday(&tp, NULL);
  return (double)tp.tv_sec + tp.tv_usec / 1000000.;
}

void sleepMs(double seconds) {
  usleep((unsigned int)(seconds*1000000));
}

void *senderfunc(void *parm) {
  srand(time(0));
  while(true) {
    int signal_id = rand()%2 + 1;
    if(signal_id == 1) {
      while(__sync_lock_test_and_set(&lock_3,1) != 0) {
      }
      usrsig1_sender_count++;
      lock_3 = 0;
      kill(getpid(), SIGUSR1);
    } else {
      while(__sync_lock_test_and_set(&lock_4,1) != 0) {
      }
      usrsig2_sender_count++;
      lock_4 = 0;
      kill(getpid(), SIGUSR2);
    }


    int r = rand()%10 + 1;
    double s = (double)r/100;
    sleepMs(s);
  }
}

void *handlerfunc(void *parm)
{
  int *index = (int *)parm;
  sigset_t set;
  sigemptyset(&set);
  //cout << (*index) << endl;
  if((*index) % 2 == 0) {
    sigaddset(&set, SIGUSR1);
  } else {
    sigaddset(&set, SIGUSR2);
  }


  int sig;

  while(true) {
    sigwait(&set, &sig);
    //cout << "Handler" << endl;
    if (sig == SIGUSR1) {
      while(__sync_lock_test_and_set(&lock_1,1) != 0) {
      }
      usrsig1_handler_count++;        
      lock_1 = 0;
    } else if(sig == SIGUSR2) {
      while(__sync_lock_test_and_set(&lock_2,1) != 0) {
      }
      usrsig2_handler_count++;
      lock_2 = 0;
    }

    sleepMs(0.0001);
  }

}

void *monitorfunc(void *parm) {

  sigset_t set;
  sigemptyset(&set);

  sigaddset(&set, SIGUSR1);
  sigaddset(&set, SIGUSR2);

  int sig;  

  while(true) {
    sigwait(&set, &sig);
    //cout << "Monitor" << endl;
    if(sig == SIGUSR1) {
      time_1[usrsig1_monitor_count] = timestamp();
      usrsig1_monitor_count++;
    } else if(sig == SIGUSR2) {
      time_2[usrsig2_monitor_count] = timestamp();
      usrsig2_monitor_count++;
    }
    monitor_count++;
    //cout << monitor_count << endl;

    if(monitor_count == NUM_SIGNAL_REPORT) {
      double difference_1 = 0;
      double difference_2 = 0;
      if(usrsig1_monitor_count > 1) {
        for(int i=0; i<usrsig1_monitor_count-1; i++) {
          difference_1 = difference_1 + time_1[i+1] - time_1[i];
        }
        cout << "Interval SIGUSR1 = " << difference_1/(usrsig1_monitor_count-1)<< endl;
      }

      if(usrsig2_monitor_count > 1) {
        for(int i=0; i<usrsig2_monitor_count-1; i++) {
          difference_2 = difference_2 + time_2[i+1] - time_2[i];
        }
        cout << "Interval SIGUSR2 = " << difference_2/(usrsig2_monitor_count-1) << endl;
      }
      cout << "Count SIGUSR1 = " << usrsig1_sender_count << endl;
      cout << "Count SIGUSR2 = " << usrsig2_sender_count << endl; 
      monitor_count = 0;
      usrsig1_monitor_count = 0;
      usrsig2_monitor_count = 0;
    }

    sleepMs(0.001);

  }
}

int main(int argc, char **argv)
{
  if(argc != 2) {
    cout << "Required parameters missing. " << endl;
    cout << "Option 1 = 1 which means run for 30 seconds" << endl;
    cout << "Option 2 = 2 which means run until 100000 signals" << endl;
    exit(0);
  }

  int option = atoi(argv[1]);
  int i;

  pthread_t handlers[NUM_HANDLER_PROCESSES];
  pthread_t generators[NUM_SENDER_PROCESSES];
  pthread_t monitor;

  sigset_t set;
  sigset_t oldset;
  sigemptyset(&oldset);
  sigemptyset(&set);
  sigaddset(&set, SIGUSR1);
  sigaddset(&set, SIGUSR2);

  pthread_sigmask(SIG_BLOCK, &set, &oldset);


  int handler_mask[4] = {0,1,2,3};
  //Initializing the handler threads
  for(i=0; i<NUM_HANDLER_PROCESSES; i++) {
    pthread_create(&handlers[i], NULL, handlerfunc, (void *)&handler_mask[i]);
  }

  pthread_create(&monitor, NULL, monitorfunc, NULL);

  sleep(5);

  for(i=0; i<NUM_SENDER_PROCESSES; i++) {
    pthread_create(&generators[i], NULL, senderfunc, NULL);
  }

  if(option == 1) {
    cout << "Option 1 " << endl;
    //sleep(30);
    while(true){

    }
    exit(0);
  } else {
    while(true) {
      if((usrsig1_handler_count + usrsig2_handler_count) >= MAX_SIGNAL_COUNT) {
        cout << "Count SIGUSR1 = " << usrsig1_handler_count << endl;
        cout << "Count SIGUSR2 = " << usrsig2_handler_count << endl;
        exit(0);
      } else {
        pthread_yield();
      }
    }
  }
}

您可以看到监视器的突发,后面是处理程序的突发。然而,在代码中,一旦处理程序/监视器处理了一个信号并执行sigwait,我就添加了一个sleep调用,以便将该回合传递给下一个可用线程。然而,这并没有帮助。我想这应该是统一的。然而,监视器仍然会被触发并打印。即使在监视器中,我在它完成信号的工作后放置了sleep,但在代码中,您看到的结果有两个不同的问题

第一个也是最重要的一个是为每个线程分配一个运行时间片。这个时间片可以被信号或IO中断,而不是线程将一直运行直到它完成它的时间片。因此,即使您设置了睡眠-如果睡眠时间小于该线程的时间片,它也不会将执行转移到其他线程。如果我记得在Windows上,这个时间片至少为5ms,但通常为40ms(尽管我可能有错误的数字)。在linux上,这个时间段可能更短,但对于通用linux机器,我认为是一样的。我曾经使用Sleep(0)放弃Windows上的时间片。usleep(0)也可以这样做。因此,你使用睡眠的方式不会达到你想要的效果。然而,由于您使用的是pthreads,所以只需调用pthread\u yield即可放弃CPU或sched\u yield(),这应该是更好的实践,但谁知道呢

测试输出可能面临的第二个问题是,在多线程环境中,实际上无法直接控制输出到流的字符顺序。如果您真的希望输出正常,那么您需要实现一个单独的线程来执行输出,并使用队列和一些锁定机制(临界区、互斥)或自由锁定机制向i发送消息


希望这会让您朝着正确的方向前进

您的代码会出现两个不同的问题,让您看到结果

第一个也是最重要的一个是为每个线程分配一个运行时间片。这个时间片可以被信号或IO中断,而不是线程将一直运行直到它完成它的时间片。因此,即使您设置了睡眠-如果睡眠时间小于该线程的时间片,它也不会将执行转移到其他线程。如果我记得在Windows上,这个时间片至少为5ms,但通常为40ms(尽管我可能有错误的数字)。在linux上,这个时间段可能更短,但对于通用linux机器,我认为是一样的。我曾经使用Sleep(0)放弃Windows上的时间片。usleep(0)也可以这样做。因此,你使用睡眠的方式不会达到你想要的效果。然而,由于您使用的是pthreads,所以只需调用pthread\u yield即可放弃CPU或sched\u yield(),这应该是更好的实践,但谁知道呢

测试输出可能面临的第二个问题是,在多线程环境中,实际上无法直接控制输出到流的字符顺序。如果您真的希望输出正常,那么您需要实现一个单独的线程来执行输出,并使用队列和一些锁定机制(临界区、互斥)或自由锁定机制向i发送消息


希望这会让你走上正确的方向。我不明白。当处理程序/监视器从sigwait中醒来时,我正在打印。因为我一直在睡觉,所以他们应该轮流醒来。我的意思是,我在监视器线程上使用了sigwait,它处理信号,然后休眠。同时,处理程序线程获得CPU时间,从sigwait中醒来,处理信号并进入睡眠状态。所以他们应该轮流进行,不是吗?即使我使用sleep,有没有办法知道为什么同一个线程有机会使用sigwait解除信号阻塞并处理它?你的问题是什么?你想知道为什么线程时间分布不均匀吗?是的,这是我的问题。信号一经处理,我就放弃使用sleep命令。那么,为什么会有大量的电话呢。我的意思是,当我放弃使用sleep命令时,监视器和处理程序会发出阵阵呼叫them@user34790:请使用“编辑”按钮将内容添加到您的帖子。@K-ballo。我不明白。当处理程序/监视器从sigwait中醒来时,我正在打印。因为我一直在睡觉,所以他们应该轮流醒来。我的意思是,我在监视器线程上使用了sigwait,它处理信号,然后休眠。同时,处理程序线程获得CPU时间,从sigwait中醒来,处理信号并进入睡眠状态。所以他们应该轮换,不是吗?有没有办法知道即使我使用睡眠,为什么同一个线程有机会解锁
HandlerHandler

Handler
Handler
Monitor
Monitor
Monitor
Monitor
Monitor
Monitor
Monitor
Monitor
Monitor
Monitor
Monitor
Monitor
Monitor
Monitor
Handler
Handler
Handler
Handler
Handler
Handler
Handler
Handler
Handler
Handler