2012-01-29 141 views
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对象不能再改变,所以我删除挥发性类规范,以便能够调用常量方法。

的对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对象是易变的?

回答

1

volatile在下列情况下,使用每MSDN:

volatile关键字是用于声明一个 对象可以在程序中的东西,如 操作系统改性类型限定符,所述硬件或同时执行的线程。声明为volatile

对象在一定的优化 不使用,因为它们的值可以在任何时候改变。即使先前的指令要求来自同一对象的值,系统始终会在要求的位置读取易失性对象的当前值 , 。 另外,对象的值立即写入赋值。

您的情况的问题是,您的NewEndPoint实际上多久改变一次?你在线程A中创建一个连接,然后你做一些工作。在发生这种情况时,没有其他任何东西可以摆弄您的端点,因为它被互斥锁锁定。所以,根据我的分析以及我在代码中可以看到的内容,这个变量不一定会发生变化。

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

当询问是否应该是volatile时,需要进行这种分析。

而且,在你的线程安全,这些功能会发生什么:

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

使用任何共享状态的从你的Worker类他们?他们是否正在共享和修改其他线程使用的其他状态?如果是的话,你需要做适当的同步。

如果没有,那么你没事。

线程化需要一些思考,你需要问自己这些问题。你需要看看所有的状态,并想知道你是否在分享。如果你正在处理指针,那么你需要怀疑谁拥有指针,以及你是否曾经意外地在线程中分享它,并据此采取行动。如果您将指针传递给在另一个线程中运行的函数,那么您将共享该指针指向的对象。如果您在这个新线程中更改了它指向的内容,那么您正在共享并需要同步。