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 构造多线程的临界截面_C_Multithreading_File_Producer Consumer_Critical Section - Fatal编程技术网

C 构造多线程的临界截面

C 构造多线程的临界截面,c,multithreading,file,producer-consumer,critical-section,C,Multithreading,File,Producer Consumer,Critical Section,我有一个生产者线程,它从源文件读取每个字符及其偏移量,然后将其写入共享循环缓冲区。 我还有一个消费线程,它读取缓冲区中最旧的元素,然后将其写入副本文件。 生产者和消费者线程的数量作为命令行参数给出,并且每次生产者/消费者线程读取或写入缓冲区,或读取或写入文件时,特定的一行写入日志文件。 现在我有一个关于生产者和消费者线程的关键部分。我如何构建它,以尽可能减少在关键部分花费的时间(速度越来越慢)。我想为我的生产者和消费者线程设置多个关键部分。例如,在我的producer线程中,我可以有

我有一个生产者线程,它从源文件读取每个字符及其偏移量,然后将其写入共享循环缓冲区。

我还有一个消费线程,它读取缓冲区中最旧的元素,然后将其写入副本文件。

生产者和消费者线程的数量作为命令行参数给出,并且每次生产者/消费者线程读取或写入缓冲区,或读取或写入文件时,特定的一行写入日志文件。

现在我有一个关于生产者和消费者线程的关键部分。我如何构建它,以尽可能减少在关键部分花费的时间(速度越来越慢)。我想为我的生产者和消费者线程设置多个关键部分。例如,在我的producer线程中,我可以有一个关键部分用于读取源文件并将特定行(例如“从文件读取”)写入日志文件,另一个关键部分用于写入缓冲区并将特定行(例如“写入缓冲区”)写入日志文件。但是,如果关键部分是一个接一个的,这又有什么区别呢?

以下是我的制作人帖子:

void *INthread(void *arg)
{
    printf("INSIDE INthread\n");
    FILE *srcFile = (FILE*)arg;
    FILE *lp; // Log file pointers.
    int t_id = INid++; // Thread number.
    int curOffset;
    BufferItem result;
    struct timespec t;

    t.tv_sec = 0;
    t.tv_nsec = rand()%(TEN_MILLIS_IN_NANOS+1);
    nanosleep(&t, NULL);

    fseek(srcFile, 0, SEEK_CUR);
    curOffset = ftell(srcFile); // Save the current byte offset.

    fseek(srcFile, 0, SEEK_END);
    if(len == 0) // If len hasnt been set by the first IN thread yet.
        len = ftell(srcFile); // Save the length of the srcFile (number of chars).

    fseek(srcFile, curOffset, SEEK_SET); // Revert file pointer to curOffset.
    printf("ID %d number of bytes %d\n", t_id, len);

    int offs;
    int ch;
    while(len > 0) // Go through each byte/char in file.
    {

        /*** CRITICAL SECTION ********************************/
        sem_wait(&empty); /* acquire the empty lock */
        pthread_mutex_lock( &pt_mutex );
        if(len > 0){
            fseek(srcFile, 0, SEEK_CUR);
            if((offs = ftell(srcFile)) != -1)
                result.offset = offs;     /* get position of byte in file */
            if((ch = fgetc(srcFile)) != EOF)
                result.data = ch;       /* read byte from file */

            // Write to log file "read_byte PTn Ox Bb I-1".
            if (!(lp = fopen(log, "a"))) {
                printf("could not open log file for writing");
            }
            if(fprintf(lp, "read_byte PT%d O%d B%d I-1\n", t_id, offs, ch) < 0){
                printf("could not write to log file");
            }
            printf("ID %d --- offset %d char %c len%d\n", t_id, result.offset, result.data, len);
            addItem(&cBuff, &result);

            // Write to log file "produce PTn Ox Bb Ii  ".
            if(fprintf(lp, "produce PT%d O%d B%d I%d\n", t_id, offs, ch, cBuff.lastInd) < 0){
                printf("could not write to log file");
            }
            fclose(lp);

            len--;
        }
        pthread_mutex_unlock( &pt_mutex );
        sem_post(&full); /* signal full */
        /*** END CRITICAL SECTION ********************************/

        t.tv_sec = 0;
        t.tv_nsec = rand()%(TEN_MILLIS_IN_NANOS+1);
        nanosleep(&t, NULL);
    }

    inJoin[t_id] = 1; // This IN thread is ready to be joined.
    printf("EXIT INthread\n");
    pthread_exit(0);
}
void *OUTthread(void *arg)
{
    printf("INSIDE OUTthread\n");
    struct timespec t;
    t.tv_sec = 0;
    t.tv_nsec = rand()%(TEN_MILLIS_IN_NANOS+1);
    nanosleep(&t, NULL);

    int processing = 1;
    FILE *targetFile, *lp;
    BufferItem OUTresult;
    int t_id = OUTid++;
    int offs, ch;
    int numBytes = len;

    while(processing){

        /*** CRITICAL SECTION ********************************/
        sem_wait(&full); /* acquire the full lock */
        pthread_mutex_lock( &pt_mutex );
        cbRead(&cBuff, &OUTresult);
        offs = OUTresult.offset;
        ch = OUTresult.data;

        if (!(lp = fopen(log, "a"))) {
            printf("could not open log file for writing");
        }
        // Write to log file "consume CTn Ox Bb Ii".
        if(fprintf(lp, "consume CT%d O%d B%d I%d\n", t_id, offs, ch, cBuff.lastInd) < 0){
            printf("could not write to log file");
        }

        printf("From buffer: offset %d char %c\n", OUTresult.offset, OUTresult.data);
        if (!(targetFile = fopen(arg, "r+"))) {
            printf("could not open output file for writing");
        }
        if (fseek(targetFile, OUTresult.offset, SEEK_SET) == -1) {
            fprintf(stderr, "error setting output file position to %u\n",
                    (unsigned int) OUTresult.offset);
            exit(-1);
        }
        if (fputc(OUTresult.data, targetFile) == EOF) {
            fprintf(stderr, "error writing byte %d to output file\n", OUTresult.data);
            exit(-1);
        }

        // Write to log file "write_byte CTn Ox Bb I-1".
        if(fprintf(lp, "write_byte CT%d O%d B%d I-1\n", t_id, offs, ch) < 0){
            printf("could not write to log file");
        }
        fclose(lp);
        fclose(targetFile);

        pthread_mutex_unlock( &pt_mutex );
        sem_post(&empty); /* signal empty */
        /*** END CRITICAL SECTION ********************************/

        t.tv_sec = 0;
        t.tv_nsec = rand()%(TEN_MILLIS_IN_NANOS+1);
        nanosleep(&t, NULL);

    }

    outJoin[t_id] = 1; // This OUT thread is ready to be joined.
    printf("EXIT OUTthread\n");
    pthread_exit(0);

}
void*INthread(void*arg)
{
printf(“内部INthread\n”);
FILE*srcFile=(FILE*)参数;
FILE*lp;//日志文件指针。
int t_id=INid++;//线程数。
int-curOffset;
项目结果;
结构timespect;
t、 tv_sec=0;
t、 tv\u nsec=rand()%(十毫英寸+1);
奈米睡眠(&t,空);
fseek(srcFile,0,SEEK\u CUR);
curOffset=ftell(srcFile);//保存当前字节偏移量。
fseek(srcFile,0,SEEK_END);
if(len==0)//如果第一个线程尚未设置len。
len=ftell(srcFile);//保存srcFile的长度(字符数)。
fseek(srcFile,curOffset,SEEK_SET);//将文件指针还原到curOffset。
printf(“ID%d字节数%d\n”,t\u ID,len);
输入输出;
int-ch;
while(len>0)//遍历文件中的每个字节/字符。
{
/***临界截面********************************/
sem_wait(&empty);/*获取空锁*/
pthread_mutex_lock(&pt_mutex);
如果(len>0){
fseek(srcFile,0,SEEK\u CUR);
如果((offs=ftell(srcFile))!=-1)
result.offset=offs;/*获取字节在文件中的位置*/
如果((ch=fgetc(srcFile))!=EOF)
result.data=ch;/*从文件中读取字节*/
//写入日志文件“读取字节PTn Ox Bb I-1”。
如果(!(lp=fopen(log,“a”)){
printf(“无法打开日志文件进行写入”);
}
如果(fprintf(lp,“读取字节PT%d O%d B%d I-1\n”,t\u id,offs,ch)<0){
printf(“无法写入日志文件”);
}
printf(“ID%d---offset%d char%c len%d\n”,t_ID,result.offset,result.data,len);
附加项(&cBuff,&result);
//写入日志文件“生产PTn Ox Bb Ii”。
如果(fprintf(lp,“生产零件%d O%d B%d I%d\n”,t_id,offs,ch,cBuff.lastInd)<0){
printf(“无法写入日志文件”);
}
fclose(lp);
蓝--;
}
pthread_mutex_unlock(&pt_mutex);
sem_post(&full);/*信号已满*/
/***端部临界截面********************************/
t、 tv_sec=0;
t、 tv\u nsec=rand()%(十毫英寸+1);
奈米睡眠(&t,空);
}
inJoin[t_id]=1;//此IN线程已准备好加入。
printf(“退出INthread\n”);
pthread_退出(0);
}
以下是我的消费者线索:

void *INthread(void *arg)
{
    printf("INSIDE INthread\n");
    FILE *srcFile = (FILE*)arg;
    FILE *lp; // Log file pointers.
    int t_id = INid++; // Thread number.
    int curOffset;
    BufferItem result;
    struct timespec t;

    t.tv_sec = 0;
    t.tv_nsec = rand()%(TEN_MILLIS_IN_NANOS+1);
    nanosleep(&t, NULL);

    fseek(srcFile, 0, SEEK_CUR);
    curOffset = ftell(srcFile); // Save the current byte offset.

    fseek(srcFile, 0, SEEK_END);
    if(len == 0) // If len hasnt been set by the first IN thread yet.
        len = ftell(srcFile); // Save the length of the srcFile (number of chars).

    fseek(srcFile, curOffset, SEEK_SET); // Revert file pointer to curOffset.
    printf("ID %d number of bytes %d\n", t_id, len);

    int offs;
    int ch;
    while(len > 0) // Go through each byte/char in file.
    {

        /*** CRITICAL SECTION ********************************/
        sem_wait(&empty); /* acquire the empty lock */
        pthread_mutex_lock( &pt_mutex );
        if(len > 0){
            fseek(srcFile, 0, SEEK_CUR);
            if((offs = ftell(srcFile)) != -1)
                result.offset = offs;     /* get position of byte in file */
            if((ch = fgetc(srcFile)) != EOF)
                result.data = ch;       /* read byte from file */

            // Write to log file "read_byte PTn Ox Bb I-1".
            if (!(lp = fopen(log, "a"))) {
                printf("could not open log file for writing");
            }
            if(fprintf(lp, "read_byte PT%d O%d B%d I-1\n", t_id, offs, ch) < 0){
                printf("could not write to log file");
            }
            printf("ID %d --- offset %d char %c len%d\n", t_id, result.offset, result.data, len);
            addItem(&cBuff, &result);

            // Write to log file "produce PTn Ox Bb Ii  ".
            if(fprintf(lp, "produce PT%d O%d B%d I%d\n", t_id, offs, ch, cBuff.lastInd) < 0){
                printf("could not write to log file");
            }
            fclose(lp);

            len--;
        }
        pthread_mutex_unlock( &pt_mutex );
        sem_post(&full); /* signal full */
        /*** END CRITICAL SECTION ********************************/

        t.tv_sec = 0;
        t.tv_nsec = rand()%(TEN_MILLIS_IN_NANOS+1);
        nanosleep(&t, NULL);
    }

    inJoin[t_id] = 1; // This IN thread is ready to be joined.
    printf("EXIT INthread\n");
    pthread_exit(0);
}
void *OUTthread(void *arg)
{
    printf("INSIDE OUTthread\n");
    struct timespec t;
    t.tv_sec = 0;
    t.tv_nsec = rand()%(TEN_MILLIS_IN_NANOS+1);
    nanosleep(&t, NULL);

    int processing = 1;
    FILE *targetFile, *lp;
    BufferItem OUTresult;
    int t_id = OUTid++;
    int offs, ch;
    int numBytes = len;

    while(processing){

        /*** CRITICAL SECTION ********************************/
        sem_wait(&full); /* acquire the full lock */
        pthread_mutex_lock( &pt_mutex );
        cbRead(&cBuff, &OUTresult);
        offs = OUTresult.offset;
        ch = OUTresult.data;

        if (!(lp = fopen(log, "a"))) {
            printf("could not open log file for writing");
        }
        // Write to log file "consume CTn Ox Bb Ii".
        if(fprintf(lp, "consume CT%d O%d B%d I%d\n", t_id, offs, ch, cBuff.lastInd) < 0){
            printf("could not write to log file");
        }

        printf("From buffer: offset %d char %c\n", OUTresult.offset, OUTresult.data);
        if (!(targetFile = fopen(arg, "r+"))) {
            printf("could not open output file for writing");
        }
        if (fseek(targetFile, OUTresult.offset, SEEK_SET) == -1) {
            fprintf(stderr, "error setting output file position to %u\n",
                    (unsigned int) OUTresult.offset);
            exit(-1);
        }
        if (fputc(OUTresult.data, targetFile) == EOF) {
            fprintf(stderr, "error writing byte %d to output file\n", OUTresult.data);
            exit(-1);
        }

        // Write to log file "write_byte CTn Ox Bb I-1".
        if(fprintf(lp, "write_byte CT%d O%d B%d I-1\n", t_id, offs, ch) < 0){
            printf("could not write to log file");
        }
        fclose(lp);
        fclose(targetFile);

        pthread_mutex_unlock( &pt_mutex );
        sem_post(&empty); /* signal empty */
        /*** END CRITICAL SECTION ********************************/

        t.tv_sec = 0;
        t.tv_nsec = rand()%(TEN_MILLIS_IN_NANOS+1);
        nanosleep(&t, NULL);

    }

    outJoin[t_id] = 1; // This OUT thread is ready to be joined.
    printf("EXIT OUTthread\n");
    pthread_exit(0);

}
void*OUTthread(void*arg)
{
printf(“内-外线程\n”);
结构timespect;
t、 tv_sec=0;
t、 tv\u nsec=rand()%(十毫英寸+1);
奈米睡眠(&t,空);
整数处理=1;
文件*targetFile,*lp;
项目输出结果;
int t_id=OUTid++;
int offs,ch;
int numBytes=len;
while(处理){
/***临界截面********************************/
sem_wait(&full);/*获取完整锁*/
pthread_mutex_lock(&pt_mutex);
cbRead(&cBuff,&OUTresult);
offs=OUTresult.offset;
ch=OUTresult.data;
如果(!(lp=fopen(log,“a”)){
printf(“无法打开日志文件进行写入”);
}
//写入日志文件“消费CTn Ox Bb Ii”。
如果(fprintf(lp,“消耗CT%d O%d B%d I%d\n”,t_id,offs,ch,cBuff.lastInd)<0){
printf(“无法写入日志文件”);
}
printf(“从缓冲区:偏移量%d字符%c\n”,OUTresult.offset,OUTresult.data);
如果(!(targetFile=fopen(arg,“r+”)){
printf(“无法打开输出文件进行写入”);
}
if(fseek(targetFile,OUTresult.offset,SEEK_SET)=-1){
fprintf(stderr,“将输出文件位置设置为%u时出错\n”,
(无符号整数)OUTresult.offset);
出口(-1);
}
if(fputc(OUTresult.data,targetFile)==EOF){
fprintf(stderr,“将字节%d写入输出文件时出错”,OUTresult.data);
出口(-1);
}
//写入日志文件“写入字节CTn Ox Bb I-1”。
if(fprintf(lp,“写入字节CT%d O%d B%d I-1\n”,t\u id,offs,ch)<0){
printf(“无法写入日志文件”);
}
fclose(lp);
fclose(targetFile);
pthread_mutex_unlock(&pt_mutex);
sem_post(&empty);/*信号为空*/
/***端部临界截面********************************/
t、 tv_sec=0;
t、 tv\u nsec=rand()%(十毫英寸+1);
奈米睡眠(&t,空);
}
outJoin[t_id]=1;//此OUT线程已准备好加入。
printf(“退出线程\n”);
pthread_退出(0);
}

我会将其组织化,使您的代码呈现以下形式:

... processing ...
mutex lock
resource read / write
mutex unlock
... continue processing
围绕要共享的每个资源。因此,您最终将拥有mul