繁体   English   中英

C ++线程意外地在同一行上多次打印

[英]C++ Threads Unexpectedly printing multiple times same line

我正在编写一个程序,目的是通过打印每个线程中的内容来查看线程的调度。 我得到的是一些意外的输出。

尽管我在循环中的每个print语句之后更新变量的值,但输出显示print语句在更新变量值之前对相同的变量值执行了多次。

为什么会发生???

我期待以下结果,

53674444272163,T35,1
53674444562178,T35,2
53674444563927,T35,3
53674444565225,T35,4

但实际上我得到以下结果。

53674444272163,T35,1
53674444272163,T35,1
53674444272163,T35,1
53674444272163,T35,1
53674444272163,T35,1
53674444272163,T35,1
53674444272163,T35,1
53674444562178,T35,2
53674444562178,T35,2
53674444562178,T35,2
53674444562178,T35,2
53674444562178,T35,2
53674444562178,T35,2
53674444562178,T35,2
53674444563927,T35,3
53674444563927,T35,3
53674444563927,T35,3
53674444563927,T35,3
53674444563927,T35,3
53674444563927,T35,3
53674444563927,T35,3
53674444565225,T35,4
53674444565225,T35,4
53674444565225,T35,4
53674444565225,T35,4
53674444565225,T35,4
53674444565225,T35,4
53674444565225,T35,4

这是我的程序

#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>
#include <sys/resource.h>
#include <sys/types.h>
#include <assert.h>
#include <stdlib.h>
#include <stdint.h>

#define NTHREADS 100
#define MAX_COUNT 1000

using namespace std;
std::ostringstream out1;
ofstream fp1;

pthread_mutex_t     mutex1 = PTHREAD_MUTEX_INITIALIZER;

unsigned long long int rdtsc_start(void)
{
   unsigned a, d;
   __asm__ volatile("rdtsc" : "=a" (a), "=d" (d));
   return ((unsigned long long)a) | (((unsigned long long)d) << 32);;
}

/* This is our thread function.  It is like main(), but for a thread*/
void *threadA(void *arg)
{ 
    long my_id = (long)arg;
    int check=0;
    volatile long count = 0;
    int j=0;
    while(count++< MAX_COUNT)
    {
        unsigned long long time_x=rdtsc_start();
        pthread_mutex_lock(&mutex1);
        out1<<time_x<<",T"<<my_id<<","<<count<<"\n";
        pthread_mutex_unlock(&mutex1);

        // busy wait  to consume CPU
        volatile long  ii=0;
        while(ii++<50000);
    }
    fp1<<out1.str();
    pthread_exit(NULL);
    return NULL;
}

int main(void)
{
    pid_t pid;
    pid=getpid();

    printf("Thread pid %d\n",pid);

    fp1.open("result_Threaded_Process1.txt"); // in place of parent process 

    pthread_t             threadid[NTHREADS];
    int result;
    //printf("Create %d threads\n", NTHREADS);
    for(long i=0; i<NTHREADS; ++i) 
    {
        result= pthread_create(&threadid[i], NULL, threadA, (void *)i);
        if(result ==-1)
        {
            perror("Thread Creation Error: \n");
            exit(EXIT_FAILURE);
        }    
    }

    //  printf("Wait for threads and cleanup\n");
    for (long i=0; i<NTHREADS; ++i)
    {
        pthread_join(threadid[i], NULL);
    }
    fp1.close(); 
    return 0;
}

我在哪里犯错? 在此先感谢您提供理解输出的任何线索或提示。

我在Ubuntu 12.04下使用g ++。

编辑

接受的答案:

根据@杰森的评论,当我把

pthread_mutex_lock(&mutex1);
fp1<<out1.str();
pthread_mutex_unlock(&mutex1);

在主要功能内部,我得到预期的结果

53674444272163,T35,1
53674444562178,T35,2
53674444563927,T35,3
53674444565225,T35,4

而当我把

   pthread_mutex_lock(&mutex1);
   fp1<<out1.str();
   pthread_mutex_unlock(&mutex1);

我正在打印NTHREAD次的相同语句(53674444272163,T35,1)。打印了NTHREAD次的(53674444562178,T35,2)。

据我了解,我得到的输出是因为尽管每个线程仅一次正确地写入输出值,

53674444272163,T35,1 53674444562178,T35,2

所有线程在退出时都打印out1的值,因此总的来说,我在NTHREAD时间内打印了相同的语句。

现在,我的问题是为什么我没有像原始程序中那样在没有互斥体的情况下在NTHREAD时间上打印(53674444272163,T35,1)?

另外,有时候,按照我的原始程序没有互斥锁,我会遇到26773分段错误(内核已转储) ,而使用互斥锁时,从未发生分段错误。 为什么这样 ???

谢谢 。

我无法在您的盒子(4个核)上复制您的结果,但是我发现了一些东西:

  1. 您正在打印出超过1 NTHREAD次的结果(在线程末尾)。 您应该仅在所有线程完成之后(在pthread_joins之后在main()中)打印出out1的值

  2. 在读取用于打印到fp1的互斥锁时,您无需将其放置在out1上。 如果您接受建议#1并不重要,但我认为我会出于教育目的指出它。

我认为#1是您的问题。 希望这可以帮助。

您正在将指向“ i”的指针传递给正在旋转的线程。 随着循环的开始,这种情况将会改变。 我本来希望奇怪的行为与您看到的有所不同,但是请尝试将传入的id更改为每个create_thread调用的新ID,如下所示:

    for(long i=0; i<NTHREADS; ++i) 
    {
        int *id = new int;
        *id = i;
        result= pthread_create(&threadid[i], NULL, threadA, (void *)id);
        if(result ==-1)
        {
            perror("Thread Creation Error: \n");
            exit(EXIT_FAILURE);
        }    

    }

这样做是为每个线程的id创建新的内存,并确保该值不会被main中的for循环更改,并且其他线程也无法访问。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM