Reentrancy and Thread-Safety

  • A thread-safe function can be called simultaneously from multiple threads, even when the invocations use shared data, because all references to the shared data are serialized.
  • A reentrant function can also be called simultaneously from multiple threads, but only if each invocation uses its own data.

Hence, a thread-safe function is always reentrant, but a reentrant function is not always thread-safe.

By extension, a class is said to be reentrant if its member functions can be called safely from multiple threads, as long as each thread uses adifferent instance of the class. The class is thread-safe if its member functions can be called safely from multiple threads, even if all the threads use thesame instance of the class.

Note: Qt classes are only documented as thread-safe if they are intended to be used by multiple threads. If a function is not marked as thread-safe or reentrant, it should not be used from different threads. If a class is not marked as thread-safe or reentrant then a specific instance of that class should not be accessed from different threads.

Reentrancy

C++ classes are often reentrant, simply because they only access their own member data. Any thread can call a member function on an instance of a reentrant class, as long as no other thread can call a member function on thesame instance of the class at the same time. For example, the Counter class below is reentrant:

class Counter
{
public:
    Counter() { n = 0; }

    void increment() { ++n; }
    void decrement() { --n; }
    int value() const { return n; }

private:
    int n;
}

The class isn't thread-safe, because if multiple threads try to modify the data membern, the result is undefined. This is because the ++ and -- operators aren't always atomic. Indeed, they usually expand to three machine instructions:

  1. Load the variable's value in a register.
  2. Increment or decrement the register's value.
  3. Store the register's value back into main memory.

If thread A and thread B load the variable's old value simultaneously, increment their register, and store it back, they end up overwriting each other, and the variable is incremented only once!

Thread-Safety

Clearly, the access must be serialized: Thread A must perform steps 1, 2, 3 without interruption (atomically) before thread B can perform the same steps; or vice versa. An easy way to make the class thread-safe is to protect all access to the data members with a QMutex:

class Counter
{
public:
    Counter() { n = 0; }

    void increment() { QMutexLocker locker(&mutex); ++n; }
    void decrement() { QMutexLocker locker(&mutex); --n; }
    int value() const { QMutexLocker locker(&mutex); return n; }

private:
    mutable QMutex mutex;
    int n;
};


http://doc.qt.io/qt-5/threads-reentrancy.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值