我正在尝试创建多个线程并尝试找出调度顺序以及它们何时完成。 每次线程获得 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
,您不需要使用互斥体来格式化自己的流。