我正在尝试创建多个线程并尝试找出调度顺序以及它们何时完成。 每次线程获得 CPU 时,它都会执行一些计算,然后等待一些 x 时间(1000ns)作为繁忙等待 然后去 sleep 。每当一个线程获得 CPU 时,它也会打印时间,以便我稍后可以找到 特定线程获得 CPU 的时间和顺序。

为了使线程安全,我使用互斥体,但它仍然没有给出正确的结果。 我哪里出错了?任何帮助将不胜感激。

我在linux下使用g++。

注意:我无法使用文件,因为在这种情况下文件打开/关闭会产生开销。

这是我的程序输出

Output : 
 
$ sort -t , -k4,4n -k5,5n -k6,6n >a.txt 
$ head a.txt  
thread,   thread_no, iteration, time_min, time_sec, time_microsec     
foo, 
foo,14,987 
foo,32 
foo,32,985, 
foo,57,970 
foo,71,933, 
foo,71,933, 
foo,71,933, 
foo,71,933, 
 
$ tail a.txt   
thread,   thread_no, iteration, time_min, time_sec, time_microsec 
foo,98,991,40,05,935379  
foo,98,992,40,05,935442  
foo,98,993,40,05,935506  
foo,98,994,40,05,935569  
foo,98,995,40,05,935633  
foo,98,996,40,05,935697  
foo,98,997,40,05,935760  
foo,98,998,40,05,935824  
foo,98,999,40,05,937914  
foo,98,1000,40,05,937994 

根据 Bart van Nierop 的评论,在释放互斥体之前添加 out.flush() 后,

这是结果。$ head a.txt

foo, 
foo, 
foo,48,991, 
foo,65, 
foo,95, 
foo,97 
foo,10,1,15,59,288329  
foo,10,1,15,59,288329  
foo,10,1,15,59,288329 

这是我的程序

#include <pthread.h> 
#include <stdio.h> 
#include <iostream> 
#include <cstdlib> 
#include <fstream> 
#include <sys/time.h> 
#include <time.h>       /* time_t, struct tm, time, localtime */ 
#include <mutex>          // std::mutex 
#include <sstream> 
 
#define BILLION  1000000000L 
#define NUM_THREADS 100 
 
std::mutex mtx;           // mutex for critical section 
 
using namespace std; 
 
 
std::string now_str() 
{ 
    struct timeval tv; 
    struct timezone tz; 
    struct tm *tm; 
    gettimeofday(&tv, &tz); 
    tm=localtime(&tv.tv_sec); 
    char buf[40]; 
    sprintf(buf,"%02d,%02d,%ld ", tm->tm_min,tm->tm_sec, tv.tv_usec);  
    return buf; 
} 
 
 
std::ostringstream out;   
/* This is our thread function.  It is like main(), but for a thread*/ 
void *threadFunc(void *arg) 
{  
      int s,j; 
      pthread_attr_t gattr; 
 
      // Assigning SCHED_RR policy  
 
      j = SCHED_RR; 
      s = pthread_attr_setschedpolicy(&gattr, j); 
      if (s != 0)  
        printf( "pthread_attr_setschedpolicy"); 
 
      s = pthread_attr_getschedpolicy(&gattr, &j); 
      if (s != 0) 
        printf( "pthread_attr_getschedpolicy"); 
 
 
    struct timespec start, stop; 
    double accum; 
 
    char *str; 
    int i = 0,k=0; 
 
    str=(char*)arg; 
 
    while(i < 1000) 
    { 
 
        ++i; 
 
        // do something here 
 
        mtx.lock();  
        out << "\nfoo," <<str<<","<<i<<"," <<now_str(); // note the timing of thread 
        mtx.unlock();   
 
 
    if( clock_gettime( CLOCK_REALTIME, &start) == -1 )  
    { 
          perror( "clock gettime" ); 
          exit( EXIT_FAILURE ); 
    } 
 
    // busy wait for 1000ns 
    do 
 
    {  
        if( clock_gettime( CLOCK_REALTIME, &stop) == -1 )  
        { 
              perror( "clock gettime" ); 
              exit( EXIT_FAILURE ); 
            } 
 
        accum = ( stop.tv_sec - start.tv_sec )* BILLION + ( stop.tv_nsec - start.tv_nsec ) ; 
 
    }while(accum < 1000); 
 
        // block the thread, to allow other thread to run 
        usleep(1); 
    } 
    std::cout<<out.str(); 
 
    return NULL; 
} 
 
int main(void) 
{ 
 
    pthread_t pth[NUM_THREADS];   
    int i = 0; 
pthread_create(&pth[0],NULL, threadFunc,  (void *) "0");  
pthread_create(&pth[1],NULL, threadFunc,  (void *) "1");  
. 
. 
. 
 
pthread_create(&pth[98],NULL, threadFunc,  (void *) "98");  
pthread_create(&pth[99],NULL, threadFunc,  (void *) "99");  
 
    for(int k=0;k<NUM_THREADS;k++) 
    pthread_join(pth[k],NULL); 
 
    return 0; 
} 

请您参考如下方法:

填充 std::ostringstream out 时您持有互斥体,但不是在将其流式传输到 std::cout 时。因此,持有互斥体的一个线程可能会发生变化 out与此同时,另一个没有互斥体的对象正在从中读取数据。

最简单的解决方法是保护您的 std::cout<<out.str();具有相同互斥体的行。

如果你关心性能,可以将全局设为std::ostringstream out一个函数局部变量(我不知道为什么你首先有这么多全局变量),以便每个线程都有自己的拷贝。然后,虽然你仍然应该保护全局 cout ,您不需要使用互斥体来格式化自己的流。


评论关闭
IT源码网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!