简体   繁体   English

为什么pthread_create()返回0但线程从不启动

[英]Why does pthread_create() returns 0 but the thread never starts

I am coming from a Java background and am comfortable using Java's synchronization for multi threaded programming. 我来自Java背景,对使用Java的同步进行多线程编程感到很满意。 Recently, I started to dabble in C++ and have had to work on some multi-threaded code. 最近,我开始涉足C ++,不得不处理一些多线程代码。 Following is the smallest working example of the issue that I am facing. 以下是我面临的问题的最小可行示例。

class TxStatus {
    private:
        int numOperations;
        bool commitStatus;
        pthread_mutex_t statusLock;

    public:
        TxStatus() {
            this->commitStatus = false;
            this->numOperations = 0;
        }
        void addNewOperation() {
            pthread_mutex_lock(&statusLock);
            numOperations++;
            pthread_mutex_unlock(&statusLock);
        }
        void operationCompleted() {
            pthread_mutex_lock(&statusLock);
            numOperations--;
            pthread_mutex_unlock(&statusLock);
        }
        void commit() {
            this->commitStatus = true;
        }

};

class TxManager {
    private:
        unsigned long long globalFrontier;
        unsigned long long txId;

        pthread_mutex_t gfLock;
        pthread_mutex_t txIdLock;

        std::map<unsigned long long, TxStatus> txStatusMap;

    public:
        TxManager() {
            pthread_mutex_lock(&gfLock);
            globalFrontier = 1;
            pthread_mutex_unlock(&gfLock);

            pthread_mutex_lock(&txIdLock);
            txId = 1;
            pthread_mutex_unlock(&txIdLock);
        }

        unsigned long long beginNewTx() {
            pthread_mutex_lock(&txIdLock);
            unsigned long long newId = txId;
            txId++;
            pthread_mutex_unlock(&txIdLock);
            TxStatus statusObj;
            txStatusMap.insert(std::make_pair(newId,statusObj));
            return newId;
        }

        void addUnflushedOperation(unsigned long long txId) {
            txStatusMap[txId].addNewOperation();
        }
        void markOperationAsFlushed(unsigned long long txId) {
            txStatusMap[txId].operationCompleted();
        }
        void markCommitted(unsigned long long txId) {
            txStatusMap[txId].commit();
        }
};


void * thread( void *args){

    TxManager txManager;
    fprintf(stderr,"Inside thread");
    unsigned long long newTxId = txManager.beginNewTx();

    fprintf(stderr,"Tx Started: %d", newTxId );
    txManager.addUnflushedOperation(newTxId);
    pthread_exit(NULL);   

}

int main(){
    pthread_t tx_thread;
    fprintf(stderr,"Inside main");
    int ret = pthread_create(&tx_thread, NULL, thread, NULL);
    if (ret != 0)
    {
        fprintf(stderr,"Error launching thread");
    }else{
        fprintf(stderr,"Thread launched successfully");
    }


    if (pthread_join(tx_thread, NULL) != 0)
    {
        fprintf(stderr,"Join pthread failed");
    }

    return 0;

}

The thread is launched successfully but I never see one of the prints from the functions executed in the thread itself ie thread(). 线程成功启动,但是我从线程本身执行的函数(即thread())中看不到任何打印结果。 If I remove the join call then the program just terminates after printing the statements inside the main method. 如果我删除了join调用,那么程序将在main方法中打印语句后终止。

Two things: 两件事情:

You appear to be missing a call to pthread_mutex_init in your constructors. 您似乎在构造函数中缺少对pthread_mutex_init的调用。 That might be part of the problem. 那可能是问题的一部分。

The other issue is that your fprintf statements need to have a newline. 另一个问题是您的fprintf语句需要换行。

That is, this line: 也就是说,这一行:

fprintf(stderr,"Inside thread");

Updated to this: 更新为:

fprintf(stderr,"Inside thread\n");

The \\n char will flush the output buffers such that your messages actually appear on the screen. \\n char将刷新输出缓冲区,以便您的消息实际出现在屏幕上。

Apply similar treatment for the other print statements. 对其他打印语句进行类似处理。

Also, you appear to be using a different lock per variable. 同样,您似乎对每个变量使用了不同的锁。 Consider just having one single mutex instance. 考虑只具有一个互斥体实例。 And you may not need a lock in TxStatus either.... 而且您可能也不需要锁定TxStatus。

Pthreads is a C library. Pthreads是一个C库。 Its data types are dumb C types. 它的数据类型是哑C类型。 If you just place them in a class or struct, they won't get auto-initialized. 如果仅将它们放在类或结构中,它们将不会自动初始化。 You need to initialize them. 您需要初始化它们。 The easiest way to do it is with PTHREAD_MUTEX_INITIALIZER (alternatively with pthread_mutex_init ) which in C++, you can do right next to the member declaration. 最简单的方法是使用PTHREAD_MUTEX_INITIALIZER (或者使用pthread_mutex_init ),在C ++中,您可以在成员声明旁边进行操作。

This doesn't hang: 这不会挂起:

#include <pthread.h>
#include <map>
#include <stdio.h>
using namespace std;
class TxStatus {
    private:
        int numOperations;
        bool commitStatus;
        pthread_mutex_t statusLock = PTHREAD_MUTEX_INITIALIZER;

    public:
        TxStatus() {
            this->commitStatus = false;
            this->numOperations = 0;
        }
        void addNewOperation() {
            pthread_mutex_lock(&statusLock);
            numOperations++;
            pthread_mutex_unlock(&statusLock);
        }
        void operationCompleted() {
            pthread_mutex_lock(&statusLock);
            numOperations--;
            pthread_mutex_unlock(&statusLock);
        }
        void commit() {
            this->commitStatus = true;
        }

};

class TxManager {
    private:
        unsigned long long globalFrontier;
        unsigned long long txId;

        pthread_mutex_t gfLock = PTHREAD_MUTEX_INITIALIZER;
        pthread_mutex_t txIdLock = PTHREAD_MUTEX_INITIALIZER;

        std::map<unsigned long long, TxStatus> txStatusMap;

    public:
        TxManager() {
            pthread_mutex_lock(&gfLock);
            globalFrontier = 1;
            pthread_mutex_unlock(&gfLock);

            pthread_mutex_lock(&txIdLock);
            txId = 1;
            pthread_mutex_unlock(&txIdLock);
        }

        unsigned long long beginNewTx() {
            pthread_mutex_lock(&txIdLock);
            unsigned long long newId = txId;
            txId++;
            pthread_mutex_unlock(&txIdLock);
            TxStatus statusObj;
            txStatusMap.insert(std::make_pair(newId,statusObj));
            return newId;
        }

        void addUnflushedOperation(unsigned long long txId) {
            txStatusMap[txId].addNewOperation();
        }
        void markOperationAsFlushed(unsigned long long txId) {
            txStatusMap[txId].operationCompleted();
        }
        void markCommitted(unsigned long long txId) {
            txStatusMap[txId].commit();
        }
};


void * thread( void *args){

    TxManager txManager;
    fprintf(stderr,"Inside thread\n");
    unsigned long long newTxId = txManager.beginNewTx();

    fprintf(stderr,"Tx Started: %llu", newTxId );
    txManager.addUnflushedOperation(newTxId);
    pthread_exit(NULL);   

}

int main(){
    pthread_t tx_thread;
    fprintf(stderr,"Inside main\n");
    int ret = pthread_create(&tx_thread, NULL, thread, NULL);
    if (ret != 0)
    {
        fprintf(stderr,"Error launching thread");
    }else{
        fprintf(stderr,"Thread launched successfully");
    }


    if (pthread_join(tx_thread, NULL) != 0)
    {
        fprintf(stderr,"Join pthread failed");
    }

    return 0;

}

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

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