如果在并行部分中执行,则引发错误

Throw an error if executed in a parallel section?

本文关键字:错误 执行 并行部 如果      更新时间:2023-10-16

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

例如,如果您考虑以下函数:

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

/* SOMETHING */会是什么?

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

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

尽管我确实认为可以在main中进行单例,以便防止从其他线程调用f的任何尝试。

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

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

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");
    }
}

一个非常、多、更好的解决方案是使随机数的检索是线程安全的。

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

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

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

而且,对于#2...你说这是一个静态随机数生成器。也许这意味着您不能再复制它,但无论如何这都值得一提。 randsrand都是这样的。但是,如果您使用的是类似 C++11 的 std::uniform_int_distribution ,则为每个线程创建一个副本应该没有问题。(如果您找不到放置每个线程副本的好位置,也许可以考虑std::thread_local