我的信号量(来自 Boost 的 named_semaphore)做错了什么?

What am I doing wrong with my semaphores (named_semaphore from Boost)?

摘要

我提供了一个小代码示例,该代码重现了我在软件中遇到的一个非常奇怪的错误。它使用 Boost 创建了 3 个命名信号量,并在一个线程中等待每个信号量。这行得通。但是如果我更改信号量的名称(通过添加给定的前缀),它不会:第 3 个信号量无缘无故地等待无限时间。

详细信息(源代码和行为)

#include <string>
#include <vector>
#include <iostream>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>
#include <boost/interprocess/sync/named_semaphore.hpp>

struct Lock
{
    std::string name;
    unsigned int count;
    Lock(const std::string& name_, unsigned int count_) : name(name_), count(count_) {}
};

int main()
{
    std::vector<Lock> locks;
    locks.push_back(Lock("Sleep1", 1));
    locks.push_back(Lock("Hello", 1));
    locks.push_back(Lock("Sleep2", 1));

    for(std::size_t i = 0; i < locks.size(); ++i)
    {
        {
            const std::string sem_name = locks[i].name;
            const unsigned int sem_count = locks[i].count;
            std::cout << "Open or Create semaphore (" << sem_name << ", " << sem_count << ")" << std::endl;
            boost::interprocess::named_semaphore semaphore(boost::interprocess::open_or_create, sem_name.c_str(), sem_count);
            std::cout << "Wait..." << std::flush;
            semaphore.wait();
            std::cout << " DONE" << std::endl;
        }
        boost::this_thread::sleep(boost::posix_time::seconds(5));
        {
            const std::string sem_name = locks[i].name;
            std::cout << "Open semaphore (" << sem_name << ")" << std::endl;
            boost::interprocess::named_semaphore semaphore(boost::interprocess::open_only, sem_name.c_str());
            std::cout << "Post..." << std::flush;
            semaphore.post();
            std::cout << " DONE" << std::endl;
        }
    }

    return 0;
}

执行此示例,我得到以下(预期)输出:

> ./sem
Open or Create semaphore (Sleep1, 1)
Wait... DONE
Open semaphore (Sleep1)
Post... DONE
Open or Create semaphore (Hello, 1)
Wait... DONE
Open semaphore (Hello)
Post... DONE
Open or Create semaphore (Sleep2, 1)
Wait... DONE
Open semaphore (Sleep2)
Post... DONE

如果我将定义信号量名称的行替换为以下内容:

std::vector<Lock> locks;
locks.push_back(Lock("CHAIN_EVALUATOR_Sleep1", 1));
locks.push_back(Lock("CHAIN_EVALUATOR_Hello", 1));
locks.push_back(Lock("CHAIN_EVALUATOR_Sleep2", 1));

执行没有终止,输出如下:

Open or Create semaphore (CHAIN_EVALUATOR_Sleep1, 1)
Wait... DONE
Open semaphore (CHAIN_EVALUATOR_Sleep1)
Post... DONE
Open or Create semaphore (CHAIN_EVALUATOR_Hello, 1)
Wait... DONE
Open semaphore (CHAIN_EVALUATOR_Hello)
Post... DONE
Open or Create semaphore (CHAIN_EVALUATOR_Sleep2, 1)
Wait...

注意新名称的奇怪选择。实际上,它失败了。它不会因 FOO_BAR_FOO_BAR_Sleep1FOOBAR_FOOBAR_Sleep1 而失败。它看起来很奇怪,我想我没有正确使用它并且我处于随机行为......

配置

编译行

g++ test_semaphore.cpp -o sem \
-I /softs/boost/1.64.0/python/2.7.9/64/gcc/4.8.5/include \
/softs/boost/1.64.0/python/2.7.9/64/gcc/4.8.5/lib/libboost_date_time-mt.a \
/softs/boost/1.64.0/python/2.7.9/64/gcc/4.8.5/lib/libboost_thread-mt.a \
/softs/boost/1.64.0/python/2.7.9/64/gcc/4.8.5/lib/libboost_system-mt.a \
-l pthread

注意:出于兼容性原因,我不使用 C++11。

Named semaphors in boost are implying Kernel or Filesystem persistence 所以当你传递 open_or_create 时,可能存在具有指定名称的命名信号量(可能来自之前中断的启动?),在这种情况下 sem_count 将被忽略并且信号量将处于它所处的任何状态。在创建或传递 create_only 标志之前尝试调用 named_semaphore::remove