拆分临界区并两次锁定互斥量是否有助于提高性能?

Is that good to improve the performance to split the critical section and lock mutex twice?

我正在尝试优化一些多线程代码。我知道我应该关注的方法是让关键部分更小,但我遇到了一些代码结构,我不确定提高性能的最佳方法是什么。

第一题是这样的:

mutex.lock();
critical Section A;
func_A(); //func_A() is just a function which will not create confliction.
critical Section B;
mutex.unlock();

func_A() 只是一个不会产生冲突的函数。 我将 A 和 B 视为一个完整的临界区,如果我拆分该部分,比方说,使 A 和 B 不在同一临界区中,例如:

mutex.lock();
critical Section A;
mutex.unlock();
func_A(); //func_A() is just a function which will not create confliction.
mutex.lock();
critical Section B;
mutex.unlock();

这会提高我的代码性能吗?

第二个问题是我有一些代码:

func1(){
    mutexA.lock();
    critical Section for varibale A;
    mutexB.lock();
    critical Section for varibale B;
    mutexB.unlock();
    critical Section for varibale A;
    mutexA.unlock();
}
func2(){
    if (some condition){
      mutexB.lock();
      critical Section for varibale B;
      mutexB.unlock();
    }
}

这里func1是一个耗时函数,func2不是。 此外,变量 B 的关键部分是一个快速部分。

将一把锁套在另一把锁的性能上可以吗?会不会太影响性能了?只对 func1 和 func2 使用一个互斥锁而不是两个互斥锁可以吗?

真的很难计算出这些互斥体的成本是多少。我真的不知道他们。

首先,保持简单但正确。然后是简介。然后,仅在需要时进行改进。

很遗憾,我无法在这里提供更具体的答案,因为:

mutex.lock();
critical Section A;
database.loadPetabyteOfData() // just a single line
critical Section B;
mutex.unlock();

这里说的很有道理。如果您的 "few lines which will not create conflict" 很快 - 不要打扰。

关于你最后一个关于为每个变量使用单独的互斥锁的例子:通常这也没有意义。如果您通常一起修改一堆变量,请使用相同的互斥锁保护它们。从更简单的版本开始。

关于你的第一个问题:如果关键部分 A 和 B 是耗时的(并且是独立的),那么拥有两个独立的部分有助于两个线程同时 运行 它们。所以,是的,在某些情况下它可能会提高性能。

关于你的第二个问题:对于轻临界区,我总是建议将它们放在同一个锁下。更少的锁也有助于避免由于程序员的错误而发生的死锁。

will this improve my code performance?

与其担心性能,不如考虑正确性。 A 和 B 独立发生是否有意义,或者它们应该是单个 "atomic"(即不可分割)操作?

如果它们是分开的、独立的动作,那么这样做可能有意义:

{
  lock_guard<mutex> l(mutex);
  critical section A
}
func_A();
{
  lock_guard<mutex> l(mutex);
  critical section B
}

但请注意,这将允许您的程序执行 AAAAAABAABBBBABBBB。

如果它执行 ABABABABABABABABAB 很重要,那么您需要将它们视为单个关键部分。

所以在不考虑性能如何影响实际行为的情况下谈论性能是错误的。如果不了解有关细节的更多细节,就不可能回答有关性能的问题。但无论如何,性能可能不是您应该担心的。