0

我需要有一个具有一个活动的类,该活动在其自己的线程中每 5 秒执行一次。它是一种 Web 服务,因此需要指定一个端点。在对象运行时,主线程可以更改端点。这是我的课:

class Worker
{
    public:
    void setEndpoint(const std::string& endpoint); 

    private:
    void activity (void);

    mutex endpoint_mutex;
    volatile std::auto_ptr<std::string> newEndpoint;

    WebServiceClient client;
} 

newEndpoint 对象是否需要声明为 volatile?如果读取处于某个循环中(以使编译器不对其进行优化),我当然会这样做,但在这里我不知道。

在每次运行中,该activity()函数都会检查新端点(如果有新端点,则将其传递给客户端并执行一些重新连接步骤)并完成其工作。

void Worker::activity(void)
{
    endpoint_mutex.lock(); //don't consider exceptions
    std::auto_ptr<std::string>& ep = const_cast<std::auto_ptr<string> >(newEndpoint);
    if (NULL != ep.get())
    {
        client.setEndpoint(*ep);
        ep.reset(NULL);
        endpoint_mutex.unlock();
        client.doReconnectionStuff();
        client.doReconnectionStuff2();
    }
    else
    {
        endpoint_mutex.unlock();
    }

    client.doSomeStuff();
    client.doAnotherStuff();
    .....
}

我锁定了互斥体,这意味着 newEndpoint 对象不能再更改,因此我删除了volatile类规范以便能够调用const方法。

setEndpoint 方法(从另一个线程调用):

void Worker::setEndpoint(const std::string& endpoint)
{
    endpoint_mutex.lock(); //again - don't consider exceptions
    std::auto_ptr<std::string>& ep = const_cast<std::auto_ptr<string> >(newEndpoint);
    ep.reset(new std::string(endpoint);
    endpoint_mutex.unlock();
}

这东西线程安全吗?如果不是,问题是什么?我需要 newEndpoint 对象是易变的吗?

4

1 回答 1

1

volatile根据 MSDN 在以下情况下使用:

volatile 关键字是一个类型限定符,用于声明对象可以在程序中被操作系统、硬件或并发执行的线程等修改。

声明为volatile的对象不会在某些优化中使用,因为它们的值可以随时更改。系统总是在请求时读取 volatile 对象的当前值,即使先前的指令要求来自同一对象的值。此外,对象的值在赋值时立即写入。

您的问题是,您的NewEndPoint实际更改频率是多少?在线程 A 中创建一个连接,然后做一些工作。在此过程中,没有其他东西可以摆弄您的端点,因为它被互斥锁锁定。因此,根据我的分析,以及我在您的代码中看到的情况,这个变量不一定会发生足够的变化。

我看不到你类的调用站点,所以我不知道你是否使用同一个类实例 100 次或更多,或者你是否正在创建新对象。

在询问某事是否应该存在时,您需要进行这种分析volatile

此外,在您的线程安全方面,这些函数中会发生什么:

 client.doReconnectionStuff();
 client.doReconnectionStuff2();

他们是否使用您Worker班级中的任何共享状态?他们是否共享和修改其他线程使用的任何其他状态?如果是,则需要进行适当的同步。

如果没有,那你没事。

线程需要一些思考,你需要问自己这些问题。您需要查看所有状态并想知道您是否在共享。如果您正在处理指针,那么您需要想知道谁拥有指针,以及您是否曾经在线程之间共享它,是否意外,并采取相应的行动。如果您将指针传递给在不同线程中运行的函数,那么您将共享指针指向的对象。如果您随后更改它在这个新线程中指向的内容,那么您正在共享并且需要同步。

于 2012-01-29T11:21:36.493 回答