【问题标题】:Thread contemporary access to variables and synchronization mechanisms线程当代访问变量和同步机制
【发布时间】:2011-09-01 20:35:26
【问题描述】:

我想了解以下代码是否正确

#include <iostream>
#include <boost/thread/thread.hpp>
#include <vector>

using namespace std;
using namespace boost;

class background_task
{
private:
    std::vector<int> numbers;

public:
    background_task()
    {
        i=0;
        numbers.assign(6000,0);
    }

    void someLongComputation()
    {
        while (++i<200)
        {
            //boost::mutex::scoped_lock(formutex);
            // cout << "Thread inside: i= " << this->i << endl;
            numbers.at(0)=i;
            cout << "Thread inside numbers= " << numbers.at(0) << endl; 
            boost::this_thread::sleep(boost::posix_time::milliseconds(100));
        }
    }

    std::vector<int>& getNumbers()
    {
        return numbers;
    }

    int i;
};

background_task f;

void valuePicker()
{
    int j=0;
    while ( (j++) < 20 )
    {
        boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
        cerr << "First number= " << f.getNumbers().at(0) << endl;
    }
}

int main(void)
{
    boost::thread comp(boost::bind(&background_task::someLongComputation, &f));
    boost::thread value(valuePicker);

    comp.join();
    return 0;
}

这段代码应该启动两个线程:一个执行 someLongComputation(我添加了一个计时器休眠器来模拟实际上非常短的 loooong 计算),另一个线程以不同的频率访问计算线程中包含的数据。

我现在想知道这种方法是否正确,因为在我看来不需要互斥锁,我想问你如何使这段代码更加线程安全和正确,因为我想我错过了一些东西.. .

传递一个非常量引用是正确的还是应该更安全地使其成为常量? 创建的数据不应该被写入,只能被读取......

谢谢!我希望通过这个线程最终解决我的初学者对多线程问题的疑虑......

【问题讨论】:

  • 线程安全不是以度数来衡量的

标签: multithreading boost asynchronous mutex pass-by-reference


【解决方案1】:

读写共享数组numbers不是线程安全的。如果此代码实际运行成功,您插入的人工sleep 可能会掩盖问题。

您需要对numbers 向量进行适当的保护,鉴于具体示例,这非常困难,因为您通过公共函数getNumbers() 将此向量公开给客户端。这样做意味着您不一定能控制background_task 的客户端实际与数据交互的方式。

我会添加一个boost::mutex(正如您已经在长计算函数中注释掉的那样),并将其锁定在长计算函数中(仅在访问数组以保持锁定范围较小时)。我还将删除getNumbers() 函数并将其替换为从数组中获取特定索引处的值的函数,例如int getNumberAt(size_t idx);,并将boost::mutex 也锁定在那里。

【讨论】:

  • 在我的真实代码中(这只是一个简单的抽象)我想拥有对整个向量的读取权限,那么我该如何正确地做到这一点呢?
  • 如果您需要对整个向量进行读取访问,那么唯一安全的选择是公开互斥锁并通过 API(和开发人员培训)强制他们在访问向量时必须锁定互斥锁,完成后解锁。这会带来更大的风险。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-11
  • 2017-09-27
相关资源
最近更新 更多