我正在尝试创建多个线程并尝试找出调度顺序以及何时完成。 每次一个线程获得CPU它执行一些计算,然后它等待一些x时间(1000ns)作为忙等待 然后去睡觉每当一个线程获得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在发布互斥锁之前添加.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;
}
答案 0 :(得分:4)
您在填充std::ostringstream out
时持有互斥锁,但在将其流式传输到std::cout
时却没有。因此,持有互斥锁的一个线程可以同时突变out
而另一个没有互斥锁从中读取它。
最简单的解决方法是使用相同的互斥锁保护您的std::cout<<out.str();
行。
如果你关心性能,你可以使全局std::ostringstream out
成为一个函数局部变量(我不知道为什么你首先有这么多全局变量),所以每个线程都有它的自己的副本。然后,虽然您仍应保护全局cout
,但您不需要使用互斥体来格式化自己的流。
答案 1 :(得分:0)
在谷歌上搜索一下,它看起来像ostringstream is not thread safe。
要获得您想要的内容,您可以自行编辑日志。
一种方法是写入大缓冲区的末尾:
uint64_t offset = 0;
char buffer[ 200000 ];
使用互斥锁写入:
mtx.lock();
offset += sprintf( buffer + offset, "\nfoo,%s,%d,%s", str, i, now_str().c_str() );
mtx.unlock();