Thread-safe vector: Is this implementation thread-safe?

前端 未结 7 1918
梦毁少年i
梦毁少年i 2021-01-16 13:22

I have a question regarding the term thread-safety. Let me give an example:

#include 
#include 

/// A thread-safe vector
class Th         


        
7条回答
  •  心在旅途
    2021-01-16 14:13

    What you have provided is thread-safe. However the problem with this is that you can't add methods that allow access to the elements without loosing thread safety. Also this kind of thread-safety is very inefficient. Sometimes you want to iterate over the whole container and sometimes you want to add many elements one after another.

    As an alternative you can put the responsibility for locking on the caller. This is much more efficient.

    /// A lockable vector
    class LockableVector
    {
    public:
        using mutex_type = std::shared_timed_mutex;
        using read_lock = std::shared_lock;
        using write_lock = std::unique_lock;
    
        // default ctor
        LockableVector() {}
    
        // move-ctor
        LockableVector(LockableVector&& lv)
        : LockableVector(std::move(lv), lv.lock_for_writing()) {}
    
        // move-assign
        LockableVector& operator=(LockableVector&& lv)
        {
            lv.lock_for_writing();
            v = std::move(lv.v);
            return *this;
        }
    
        read_lock lock_for_reading() { return read_lock(m); }
        write_lock lock_for_writing() { return write_lock(m); }
    
        // add double to vector
        void add(double d) {
            v.emplace_back(d);
        }
    
        // return length of vector
        int length() {
            return v.size();
        }
    
        // iteration
        auto begin() { return v.begin(); }
        auto end() { return v.end(); }
    
    private:
        // hidden, locked move-ctor
        LockableVector(LockableVector&& lv, write_lock)
        : v(std::move(lv.v)) {}
    
        mutex_type m;
        std::vector v;
    };
    
    int main()
    {
        LockableVector v;
    
        // add lots of elements
    
        { /// create a scope for the lock
            auto lock = v.lock_for_writing();
    
            for(int i = 0; i < 10; ++i)
                v.add(i);
        }
    
        // print elements
    
        { /// create a scope for the lock
            auto lock = v.lock_for_reading();
    
            std::cout << std::fixed << std::setprecision(3);
            for(auto d: v)
                std::cout << d << '\n';
        }
    }
    

    Also by having both read and write locks you increase efficiency because you can have multiple readers at the same time when no thread is currently writing.

提交回复
热议问题