client 持有一个指向 double
值的共享指针,server 通过持有
weak_pointer
在另一个分离线程上更新此值,服务器检查
weak_pointer
是否已过期以及是否已过期。不,它会从安全向量中删除。我怀疑这不起作用,因为
shared_ptr
可能会从客户端之间被破坏,我对
expired()
的阅读(我认为这是线程安全的,因为我想象它指的是
shared_ptr
的原子计数器)并且 我的价值更新。有没有办法让检查
expired()
和
lambda
函数在销毁之前更新值?我的意思是:
struct server
{
public:
static void subscribe(const std::shared_ptr<double>& d)
{
m_values.safe_push_back(d); //safely pushes back in the vector
}
void update()
{
auto updater = [](std::weak_ptr<double>& wd)
{
if(wd.expired()) wd = nullptr;
else *wd += 2.0; //This is not thread safe I guess?
};
m_values.safe_remove_all(nullptr);
m_values.safe_visit(updater);
};
private:
static safe_vector<std::weak_ptr<double>> m_values;
}
struct client
{
void subcribe_sleep_print(const double random_seconds)
{
std::shared_ptr<double> d = std::make_shared<double>(0.0); //for the sake of the example assume we create subscribe before sleep
server::subscribe(d);
sleep_for_seconds(random_seconds); //sleeps for some random time in seconds.
std::cout << *d << std::endl;
}
}
想象 server::update
和
client::subcribe_sleep_print
在不同的线程上运行。这不安全,因为服务器写入时
shared_ptr
可能会被破坏?有没有办法在没有用户(我)定义的原子或互斥体的情况下实现这一点?我不介意它是否在后台使用,只要我自己不添加它们(原子/互斥),因为我知道共享指针已经使用原子计数器。
else *wd += 2.0; //This is not thread safe I guess?
不,它不是线程安全的。您面临着竞争条件,在您检查过期之后,指针可能会过期。在这种情况下,您现在已取消引用 nullptr
。因此,正确的方法是显式使用
std::weak_ptr<T>::lock()
来尝试获取关联的共享指针(这也是
expired()
内部所做的),并且只有当获得有效的指针时,您才可以执行读取或写入操作访问。如果您没有获得有效的共享指针,请将其视为
expired()
返回了 false。