boost :: scoped_lock不能使用本地静态变量?

时间:2011-10-14 14:34:50

标签: c++ multithreading locking thread-safety boost-thread

我制作了以下示例程序来使用增强线程:

#pragma once
#include "boost\thread\mutex.hpp"
#include <iostream>

class ThreadWorker
{
public:
    ThreadWorker() {}
    virtual ~ThreadWorker() {}

    static void FirstCount(int threadId)
    {
        boost::mutex::scoped_lock(mutex_);
        static int i = 0;

        for(i = 1; i <= 30; i++)
        {
            std::cout << i << ": Hi from thread:  " << threadId << std::endl;
        }

    }

private:
    boost::mutex mutex_;
};

主要课程:

// ThreadTest.cpp
#include "stdafx.h"
#include "boost\thread\thread.hpp"
#include "ThreadWorker.h"

int _tmain(int argc, _TCHAR* argv[])
{
    boost::thread thread1(&ThreadWorker::FirstCount, 1);
    boost::thread thread2(&ThreadWorker::FirstCount, 2);
    boost::thread thread3(&ThreadWorker::FirstCount, 3);

    thread1.join();
    thread2.join();
    thread3.join();

    std::string input;
    std::cout << "Press <enter> to finish...\n";
    std::getline( std::cin, input );
    return 0;
}

当我运行时,我得到以下输出:

1: Hi from thread:  1
1: Hi from thread:  3
2: Hi from thread:  3
...

看起来线程1首先到达那里然后是线程3.是不是scoped_lock应该阻止其他线程进入该段代码?运行FirstCount()的第一个线程不应该完成吗?

更新

我认为我的代码有一个问题就是这一行:

boost::mutex::scoped_lock(mutex_);

我认为应该是这样的:

boost::mutex::scoped_lock xyz(mutex_);

一旦我这样做,它确实使关于mutex_的抱怨不是静态的。为什么它首先起作用我不确定。将mutex_更改为static会给我一个链接错误:

  

1&gt; ThreadWorker.obj:错误LNK2001:未解析的外部符号   “private:static class boost :: mutex ThreadWorker :: mutex_”   (?mutex_ @ ThreadWorker @@ 0Vmutex @升压@@ A)   1&gt; c:\ something \ ThreadTest \ Debug \ ThreadTest.exe:致命错误LNK1120:   1个未解决的外部

还在玩它。

4 个答案:

答案 0 :(得分:6)

您有两个错误:

首先,正如已经注意到的那样,mutex_也应该是静态的:

private:
    static boost::mutex mutex_;

当然要在某处(最好是.cpp文件中声明!):

boost::mutex ThreadWorker::mutex_{};

现在,编译器为什么不抱怨?好吧,因为你实际上没有在这里构造一个带参数mutex_的范围锁:

boost::mutex::scoped_lock(mutex_);

实际上这不会调用你想要的构造函数,而是创建一个类型为mutex_的(本地)对象scoped_lock,并由默认构造函数构造。因此,没有编译器问题。您应该将其更改为以下内容:

boost::mutex::scoped_lock l{mutex_};

现在编译器应该开始抱怨mutex_

答案 1 :(得分:3)

你有三个独立的对象,它们都不能看到对方的互斥对象,因为该成员是在每个对象中创建的。

也许你的意思是让mutex_静态?

编辑:如果我使互斥锁静态并从i变量中删除静态,那么它似乎工作,因为我猜你的意思。似乎是这样的事情:每个线程立即进入循环,并且由于互斥锁不是静态的,因此不会彼此锁定。当他们将所有输出都输出到控制台时(我不记得在写入cout时是否存在互斥)并且我得到增量,他们都将静态i视为30并退出。

编辑2:不,仍然不正确,因为在某些运行中仍然存在散布的值。

编辑3:它编译的原因是你的scoped_lock是一个临时的,它似乎让编译器抛弃了mutex_应该是静态的事实。请尝试使用以下代码:

#include <iostream>
#include "boost\thread\mutex.hpp"
#include "boost\thread\thread.hpp"

class ThreadWorker
{
public:
    ThreadWorker() {}
    virtual ~ThreadWorker() {}

    static void FirstCount(int threadId)
    {
        // Created object f here rather than temprary
        boost::mutex::scoped_lock f(mutex_);
        int i = 0; // Not static

        for(i = 1; i <= 30; i++)
        {
            std::cout << i << ": Hi from thread:  " << threadId << std::endl;
        }

    }

private:
    static boost::mutex mutex_; // Static
};

// Storage for static
boost::mutex ThreadWorker::mutex_;

int main(int argc, char* argv[])
{
    boost::thread thread1(&ThreadWorker::FirstCount, 1);
    boost::thread thread2(&ThreadWorker::FirstCount, 2);
    boost::thread thread3(&ThreadWorker::FirstCount, 3);

    thread1.join();
    thread2.join();
    thread3.join();

    std::string input;
    std::cout << "Press <enter> to finish...\n";
    std::getline( std::cin, input );
    return 0;
}

答案 2 :(得分:0)

此代码是否也使用相同的编译器进行编译?

您能看到此代码的问题吗?尝试在不编译的情况下发现问题。

class C {
public:
    static int f () {
        return i;
    }

    int i;
};

int main() {
    return C::f();
}

更新: 我刚看了你的更新。

class C {
public:
    static int f () {
        return i;
    }

    static int i;
};

int C::i = whatever;

int main() {
    return C::f();
}

答案 3 :(得分:0)

将我的代码更改为:

ThreadWorker.h:

#pragma once
#include "boost\thread\mutex.hpp"
#include <iostream>

class ThreadWorker
{ 
public:
    ThreadWorker();
    virtual ~ThreadWorker();

    static void FirstCount(int threadId);

private:
    static boost::mutex mutex_;
};

ThreadWorker.cpp:

#include "stdafx.h"
#include "ThreadWorker.h"

boost::mutex ThreadWorker::mutex_;

ThreadWorker::ThreadWorker()
{
}

ThreadWorker::~ThreadWorker()
{
}

void ThreadWorker::FirstCount(int threadId)
{
    boost::mutex::scoped_lock xyz(mutex_);
    static int i = 0;

    for(i = 1; i <= 30; i++)
    {
        std::cout << i << ": Hi from thread:  " << threadId << std::endl;
    }

}

ThreadTest.cpp:

// ThreadTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "boost\thread\thread.hpp"
#include "ThreadWorker.h"

int _tmain(int argc, _TCHAR* argv[])
{
    boost::thread thread1(&ThreadWorker::FirstCount, 1);
    boost::thread thread2(&ThreadWorker::FirstCount, 2);
    boost::thread thread3(&ThreadWorker::FirstCount, 3);

    thread1.join();
    thread2.join();
    thread3.join();

    std::string input;
    std::cout << "Press <enter> to finish...\n";
    std::getline( std::cin, input );
    return 0;
}

我做的更改是1.分隔标题和cpp文件(我最初只是为了使我的帖子更紧凑)2。给scoped_lock变量一个标识符和3.使互斥锁静态。

它现在按预期工作,从每个线程顺序打印30行。令我感到困惑的是为什么之前编译的代码(因为tinman也能够编译我的原始代码)。