简体   繁体   English

线程同步问题

[英]Thread synchronization issue

I have been given a task of copying millions of folders individually through threading in C/C++ on Linux (with some legacy code). 我的任务是通过Linux上的C / C ++中的线程(带有一些旧代码)分别复制数百万个文件夹。

The individual functionalities like scanning of folders, copying of file from source to destination folder are in place and works properly when executed in serial. 诸如文件夹扫描,文件从源文件夹复制到目标文件夹的各个功能均已就绪,并且在串行执行时可以正常工作。 The whole issue comes in when done via threading. 整个问题是通过线程完成的。

Issue: The code behaves a little differently everytime I execute it. 问题:每次执行代码时,代码的行为都会有所不同。 Sometimes it copies the entire list of folders proeprly but sometimes it fails. 有时它会正确地复制整个文件夹列表,但有时会失败。

A sample failing output is: 样本失败的输出是:

foldername is [Junk] tCount is 2 cntr is 3

val of folder is Junk tid is 3055356816

foldername is [Notes] tCount is 3 cntr is 4

val of folder is  tid is 3042966416

Folder creation failed /var/anshul/work/copyDirectoryThreaded/test_copied/email/

In the function thread the value of argument passed becomes NULL . 在函数线程中,传递的参数值变为NULL In above case the argument Notes is been passed from main function to the thread function, but in thread function the value recieved is NULL . 在上述情况下,参数Notes从主函数传递到线程函数,但是在线程函数中,接收到的值为NULL

My main code looks like this: 我的主要代码如下:

int main()
{
    int cntr=0;
    int Val = 3;

    tCount = 0;
    pthread_t thread[folderCount]; // folderCount is total number of folders scanned
    int  iret[folderCount];
    std::map<std::string,int>::iterator mFolderIt; // mFolder map contains the folder list.
    char foldername[30] = {0};

    for ( mFolderIt=mFolder.begin() ; mFolderIt != mFolder.end(); )
    {
        if(tCount < Val)
        {
            pthread_mutex_lock( &mutex_tCount );
            tCount++;
            pthread_mutex_unlock( &mutex_tCount );

            sprintf(foldername,"%s",(*mFolderIt).first.c_str() );
            fprintf(stderr, "foldername is [%s] tCount is %d cntr is %d\n",foldername,tCount,cntr);
            iret[cntr] = pthread_create( &thread[cntr], NULL,folderCopy , (void*)foldername);
            cntr++;
            usleep(1); // most crucial for threading.......
            mFolderIt++;
            memset(foldername,0,30);
        }
        else
        {
            while(tCount >= Val)
            {
                usleep(10);
            }
        }
    }

    for(int x = 0 ; x<folderCount ;x++)
        pthread_join(thread[x],NULL);

    return 1;
}

Thread function code: 线程功能代码:

void * folderCopy(void *f)
{
    fprintf(stderr,"val of folder is %s tid is %u\n", folder, (unsigned int)pthread_self());

    pthread_mutex_lock( &mutex_tCount );
    tCount--;
    pthread_mutex_unlock( &mutex_tCount );
    pthread_exit(NULL);
    return NULL;
}

Can someone please help me to solve this issue. 有人可以帮我解决这个问题。

                    fprintf(stderr, "foldername is [%s] tCount is %d cntr is %d\n",foldername,tCount,cntr);
                    iret[cntr] = pthread_create( &thread[cntr], NULL,folderCopy , (void*)foldername);
                    cntr++;
                    usleep(1); // most crucial for threading.......
                    mFolderIt++;
                    memset(foldername,0,30);

There is no guarentee that that usleep will be enough time. 没有保证说usleep足够的时间。 Instead, you should make absolutely sure that the memory will remain valid until the other thread has had a chance to use it. 相反,您应该绝对确保该内存将保持有效,直到另一个线程有机会使用它为止。 The simplest way to do this is to give the other thread its own copy of the data: 最简单的方法是给另一个线程自己的数据副本:

iret[cntr] = pthread_create(&thread[cntr], NULL, folderCopy, strdup(foldername));
// ...

void * folderCopy(void *f)
{
    char *folderName = (char *)f;
    // do something with folderName
    free(f);
    return NULL;
}

There are other ways to ensure that the thread has taken a copy of the data, but this is the simplest to get right. 还有其他方法可以确保线程获取了数据副本,但这是最简单的正确方法。

The pointer passed as the fourth parameter is not thread safe. 作为第四个参数传递的指针不是线程安全的。

pthread_create( &thread[cntr], NULL,folderCopy , (void*)foldername);

So every thread is receiving the same pointer and since the main thread is overwritting the content of this pointer so there is no way to know what content any particular thread sees. 因此,每个线程都接收相同的指针,并且由于主线程覆盖了该指针的内容,因此无法知道任何特定线程看到的内容。

You need to make a private copy of the content for each thread (then let the thread clean it up). 您需要为每个线程制作内容的私有副本(然后让线程清理它)。

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

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