c ++成员函数线程安全

时间:2012-05-12 16:13:02

标签: c++

我正在编写一个记录消息的函数。 我将从不同的线程调用此打印函数。 我的代码如下:

MyLog::printLog(const char* s)
    {

            std::string myline(s);
            //m_Mutex is class member and there will be only object for this class
            // shared by all threads
            int ret = pthread_mutex_lock(&m_Mutex);
            if ( ret != 0 )
            {
                    std::cout<<" trying to lock same mutex char* "<<std::endl;

            }


            //code to log message in File

            pthread_mutex_unlock(&m_Mutex);
     }

我的问题是,如果从不同的线程调用上面的函数,例如“from thread1”,“from thread 2”,...将会有任何机会const char * s混乱打印错误的值。 我希望我的问题很明确。

3 个答案:

答案 0 :(得分:3)

您的函数将按预期工作,因为myline是一个局部变量(每个线程都有自己的堆栈,所以它有自己的myline实例)

答案 1 :(得分:1)

如果您从不同的线程调用此函数,并且您对参数const char* s所做的任何更改都受到您的互斥锁m_Mutex的保护,那么您将会很好,并且不会有任何混乱。

编辑

实际上,每个对这个函数的调用都会在从不同的线程调用时拥有它自己的堆栈,并且看到它const char*你不能改变你的参数,所以不需要用互斥锁来保护它。

您的变量s是调用它的线程的本地变量,它是const

然后复制到局部变量myline肯定不会弄乱任何东西,因为每个线程都有它的调用堆栈,当调用此函数时,它会生成myline的实例,这是完全独立于任何其他线程。

答案 2 :(得分:1)

这取决于您如何调用printLog函数。如果传递给函数的地址的字符串被另一个线程变异,那么在日志函数中可能看不到它的一致视图。如果你传入一个指向不可变字符串的指针,例如文字,那么你就没事了。

这是一个很好的例子:

void from_thread_one()
{
    MyLog::printLog("Hello World");  // immutable string
}

void from_thread_two()
{
    MyLog::printLog("Another text");  // ditto
}

另一方面,这是一个不合适且有种族的例子:

char globalString[] = "This is a really long string";

void from_thread_one()
{
    globalString[5] = 'A';
    MyLog::printLog(globalString);
}

void from_thread_two()
{
    globalString[8] = 'Q';
    MyLog::printLog(globalString);
}

在此设置中,您正在复制字符串(通过std::string myline(s);),而s指向的数组内容可以在另一个线程中同时更改。在这种情况下,取消引用char指针也必须在临界区内发生。

您的设置的基本问题是原始字符指针没有隐含的语义,告诉用户哪种行为是可接受的,哪种行为不可接受。如果您通过值传递实际std::string,则可以消除有关同步对printLog函数中字符串的访问权限的不确定性,并将责任完全转移到调用者中。