2

在我的代码中,我有一个使用静态随机引擎生成器运行的函数,如果用户尝试从与主线程不同的线程调用此函数,我希望能够抛出错误。

例如,如果您考虑以下功能:

void f()
{
    if (/* SOMETHING */) {
        throw std::future_error("ERROR = f() : cannot be executed in parallel");
    }
}

会是/* SOMETHING */什么?

4

3 回答 3

2

我在线程方面不是很有经验,但不知何故我很想按照单例/其他设计模式做一些事情。

话虽这么说,我不相信这个想法很优雅,我不知道你为什么要这样做,所以我不知道如何提出任何替代方案......

虽然我确实认为可以在 main 中创建一个单例,这样就可以防止任何从其他线程调用 f 的尝试。

单身人士通常被滥用,所以......我会小心的。

于 2013-01-28T00:23:03.130 回答
2

尽管我认为您要实现的目标不是很优雅(锁定或保存每个线程的随机引擎生成器的状态,例如使用线程本地存储可能会更好),但这里有一个解决您所要求的解决方案:

static const auto mainThreadId = std::this_thread::get_id();

void f()
{
    if (std::this_thread::get_id() != mainThreadId) {
        throw std::future_error("ERROR = f() : cannot be executed in parallel"
            "/from a thread other than the main one");
    }
}
于 2013-01-28T12:43:14.140 回答
1

一个非常非常好的解决方案是让您检索随机数是线程安全的。

这可以通过以下两种方式之一完成:

  1. 在检索随机数时获取互斥锁。
  2. 给任何需要生成随机数的线程自己的随机对象。

让我们谈谈#1。由于您建议包装调用以获取随机数,因此使用 mutex 包装这些调用并不太牵强。我们不是简单地在运行时将问题呈现给用户(这通常是一个非常糟糕的开发选择),而是解决了这个问题。唯一的缺点是我们减慢了对随机数生成器的调用速度——这可能是可以接受的,但如果不是……请选择选项#2。

而且,对于#2 ...您说这是一个静态随机数生成器。也许这意味着您不能再制作它的副本,但这无论如何都值得一提。rand并且srand是这样的。但是,如果您使用的是 C++11 之类的东西std::uniform_int_distribution,那么为每个线程创建一个副本应该没有问题。(也许考虑std::thread_local一下你是否找不到放置每个线程副本的好地方。)

于 2013-01-28T23:39:17.420 回答