C++ 带Boost的进程间读写器锁

C++ 带Boost的进程间读写器锁,c++,boost,boost-interprocess,C++,Boost,Boost Interprocess,在解释如何使用Boost实现读写器锁时,这是一个很好的例子。它看起来相对简单,我真的很喜欢它,但它似乎也使用了一个未命名的锁,我需要一个进程间解决方案(不需要是可移植的,只能是Windows) 有没有办法让进程间共享\u互斥体?我看到有一个锁,但我不能让它与其他锁一起工作 任何指点都很感激 [编辑] 与此同时,我遇到了一个几乎一针见血的问题。我有两个问题: 它没有显示完整的代码(我猜我需要使用命名的\u upgradable\u mutex,但我不太确定)和 我不喜欢修改后的“writer”的答

在解释如何使用Boost实现读写器锁时,这是一个很好的例子。它看起来相对简单,我真的很喜欢它,但它似乎也使用了一个未命名的锁,我需要一个进程间解决方案(不需要是可移植的,只能是Windows)

有没有办法让进程间
共享\u互斥体
?我看到有一个锁,但我不能让它与其他锁一起工作

任何指点都很感激

[编辑]

与此同时,我遇到了一个几乎一针见血的问题。我有两个问题:

  • 它没有显示完整的代码(我猜我需要使用
    命名的\u upgradable\u mutex
    ,但我不太确定)和
  • 我不喜欢修改后的“writer”的答案,它没有使用现成的类来解锁析构函数,而是在互斥体上使用一系列3个原始调用

  • 欢迎评论或好的解决方案。

    Boost.Interprocess文档介绍了所谓的it支持,以及两种支持的可升级互斥类型:

    • ,一种非递归、匿名可升级的互斥体,可放置在共享内存或内存映射文件中
    • ,一个非递归的、命名为可升级的互斥体
    编辑:我相信这是可行的:

    #include <iostream>
    #include <string>
    #include <unistd.h>
    
    #include <boost/scope_exit.hpp>
    #include <boost/interprocess/mapped_region.hpp>
    #include <boost/interprocess/shared_memory_object.hpp>
    #include <boost/interprocess/sync/interprocess_upgradable_mutex.hpp>
    #include <boost/interprocess/sync/scoped_lock.hpp>
    #include <boost/interprocess/sync/sharable_lock.hpp>
    #include <boost/interprocess/sync/upgradable_lock.hpp>
    
    // http://stackoverflow.com/questions/12439099/interprocess-reader-writer-lock-with-boost/
    
    #define SHARED_MEMORY_NAME "SO12439099-MySharedMemory"
    
    struct shared_data {
    private:
        typedef boost::interprocess::interprocess_upgradable_mutex upgradable_mutex_type;
    
        mutable upgradable_mutex_type mutex;
        volatile int counter;
    
    public:
        shared_data()
            : counter(0)
        {
        }
    
        int count() const {
            boost::interprocess::sharable_lock<upgradable_mutex_type> lock(mutex);
            return counter;
        }
    
        void set_counter(int counter) {
            boost::interprocess::scoped_lock<upgradable_mutex_type> lock(mutex);
            this->counter = counter;
        }
    };
    
    int main(int argc, char *argv[])
    {
        using namespace boost::interprocess;
    
        if (argc != 2) {
            std::cerr << "Usage: " << argv[0] << " WHICH" << std::endl;
            return 1;
        }
    
        const std::string which = argv[1];
        if (which == "parent") {
            shared_memory_object::remove(SHARED_MEMORY_NAME);
            shared_memory_object shm(create_only, SHARED_MEMORY_NAME, read_write);
    
            BOOST_SCOPE_EXIT(argc) {
                shared_memory_object::remove(SHARED_MEMORY_NAME);
            } BOOST_SCOPE_EXIT_END;
    
            shm.truncate(sizeof (shared_data));
    
            // Map the whole shared memory into this process.
            mapped_region region(shm, read_write);
    
            // Construct the shared_data.
            new (region.get_address()) shared_data;
    
            // Go to sleep for a minute.
            sleep(60);
    
            return 0;
        } else if (which == "reader_child") {
            shared_memory_object shm(open_only, SHARED_MEMORY_NAME, read_write);
    
            mapped_region region(shm, read_write);
            shared_data& d = *static_cast<shared_data *>(region.get_address());
    
            for (int i = 0; i < 100000; ++i) {
                std::cout << "reader_child: " << d.count() << std::endl;
            }
        } else if (which == "writer_child") {
            shared_memory_object shm(open_only, SHARED_MEMORY_NAME, read_write);
    
            mapped_region region(shm, read_write);
            shared_data& d = *static_cast<shared_data *>(region.get_address());
    
            for (int i = 0; i < 100000; ++i) {
                d.set_counter(i);
                std::cout << "writer_child: " << i << std::endl;
            }
        }
    }
    
    (必须首先启动父级:
    /a.out父级


    输出显示“reader\u child”和“writer\u child”行的交错(所有“reader\u child”行在第一行“writer\u child”后显示非零值),因此它似乎工作正常。

    谢谢!这个技巧对我来说是否消除了一些疑问,尽管它并不完全是我想要的。当计数器被锁保护时,为什么要使用volatile?@BryanFok:我使用
    volatile
    ,因为在锁定
    进程间可升级的互斥锁时,我没有看到任何内存障碍保证。有三种实现:posix、windows和spin。如果使用posix或windows实现,我认为不需要
    volatile
    ,因为pthread_mutex_lock()/WaitForSingleObject()是在后台调用的。spin实现使用原子CAS操作,我认为有些架构中CAS没有内存屏障保证。请参阅,例如.Related:请注意,即使使用作用域锁定或共享锁定,也不能防止在程序崩溃时使进程间互斥锁处于锁定状态。我发现我需要编写一个实用程序来调用boost::interprocess::named_upgradable_mutex::remove(),以便在发生此类事件后清理互斥。在linux上,这似乎调用了shm_unlink(),尽管我不确定这就是它的全部功能。顺便说一句,您可以在/dev/shm/中看到您的命名锁。
    #!/usr/bin/env sh
    ./a.out reader_child &
    ./a.out reader_child &
    ./a.out writer_child &
    ./a.out reader_child &
    ./a.out reader_child &