lock_guard是否保护返回值?

问题描述 投票:2回答:2

我对lock_guard和返回值有疑问。我想用一些代码来说明我的问题:

class Semaphore
{
public:
    Semaphore() = delete;
    Semaphore(int n);

    /**
     * Increases semaphore by one.
     */
    void up()
    {
        std::lock_guard<std::mutex> lg(m_);
        ++n_;
    }

    /**
     * Decreases semaphore by one.
     */
    void down()
    {
        std::lock_guard<std::mutex> lg(m_);
        --n_;
    }

    /**
     * Returns the underlying value of the semaphore.
     */
    int get1() const
    {
        std::lock_guard<std::mutex> lg(m_);
        int tmp = n_;
        return tmp;
    }

    /**
     * Returns the underlying value of the semaphore.
     */
    int get2() const
    {
        std::lock_guard<std::mutex> lg(m_);
        return n_;
    }

private:
    mutable std::mutex m_;
    int n_;
};

上面的类是Semaphore的简单实现。哪种get方法是线程安全的? get2是否足够好还是我必须使用get1?我必须将内部值n_复制到临时变量还是可以立即将其返回?

此帖子归结为以下问题:lock_guard是否保护我的返回值?

c++ multithreading thread-safety mutex
2个回答
0
投票

get2()足以保护返回值。

n_由值返回,因此将使用您的return n_语句复制该变量以返回给调用方。您的lock_guard将确保n_不会被更改,直到将该副本返回给调用方,然后销毁该副本,从而释放锁定。


0
投票

从在n_上没有数据争夺的意义上来说,它们都是安全的。在lock_guard被销毁之前,首先构造返回值。

但是,您的类方法不能以线程安全的方式使用。

[如果有任何线程先调用down(),然后又调用get(),则不能保证在这两个调用之间(没有锁的情况下)另一个线程可能不会先获得锁。

您必须在锁定互斥锁且无中断的同时修改并返回该值。因此,up()down()必须返回n_。不应有get()功能。

© www.soinside.com 2019 - 2024. All rights reserved.