C++ “新功能有什么优势?”;同步的;块,在C+中+;提供?

C++ “新功能有什么优势?”;同步的;块,在C+中+;提供?,c++,multithreading,transactional-memory,C++,Multithreading,Transactional Memory,有一个新的实验特性(可能是C++20),即“同步块”。该块为代码段提供全局锁。下面是一个来自的示例 #包括 #包括 #包括 int f() { 静态int i=0; 同步的{ std::cout从表面上看,synchronized关键字在功能上类似于std::mutex,但通过引入新的关键字和相关语义(如包含同步区域的块),可以更容易地为事务性内存优化这些区域 特别是 STD::MutX 和朋友在原则上或多或少是编译器不透明的,而代码>同步< /COD>具有明确的语义。编译器不能确定标准库 ST

有一个新的实验特性(可能是C++20),即“同步块”。该块为代码段提供全局锁。下面是一个来自的示例

#包括
#包括
#包括
int f()
{
静态int i=0;
同步的{

std::cout从表面上看,
synchronized
关键字在功能上类似于
std::mutex
,但通过引入新的关键字和相关语义(如包含同步区域的块),可以更容易地为事务性内存优化这些区域

特别是 STD::MutX 和朋友在原则上或多或少是编译器不透明的,而<>代码>同步< /COD>具有明确的语义。编译器不能确定标准库<代码> STD::MutX < /C> >将很难将其转换为使用TM。C++编译器将工作正常。当

std::mutex
的标准库实现发生更改,因此无法对该行为做出许多假设时,则为y


此外,如果块没有提供同步所需的显式作用域,编译器很难对块的范围进行推理-在简单的情况下,如单作用域的
锁保护
,这似乎很容易,但在许多复杂的情况下,如锁逃逸了所需的函数编译器永远不知道在哪里可以解锁。

锁通常不能很好地组合。请考虑:

//
// includes and using, omitted to simplify the example
//
void move_money_from(Cash amount, BankAccount &a, BankAccount &b) {
   //
   // suppose a mutex m within BankAccount, exposed as public
   // for the sake of simplicity
   //
   lock_guard<mutex> lckA { a.m };
   lock_guard<mutex> lckB { b.m };
   // oversimplified transaction, obviously
   if (a.withdraw(amount))
      b.deposit(amount);
}

int main() {
   BankAccount acc0{/* ... */};
   BankAccount acc1{/* ... */};
   thread th0 { [&] {
      // ...
      move_money_from(Cash{ 10'000 }, acc0, acc1);
      // ...
   } };
   thread th1 { [&] {
      // ...
      move_money_from(Cash{ 5'000 }, acc1, acc0);
      // ...
   } };
   // ...
   th0.join();
   th1.join();
}
…无论交易是否作为一个整体进行,都可以从中受益
总之,在不使用互斥锁的情况下,不会给BankAccount造成负担,也不会因为来自用户代码的请求冲突而出现死锁风险。

不确定是否确实如此,但cppreference使第一个版本听起来像是保证按顺序打印,而AFAIK第二个版本则没有。“尽管同步块的执行就像在全局锁下一样,但实现需要检查每个块中的代码,并对事务安全代码使用乐观并发(在可用的情况下由硬件事务内存备份),而对非事务安全代码使用最小锁。"“量子物理”,“代码> STD::CuxIGueGue和 STD::MutX < /C>不是C++语言的一部分:它们只是库中定义的类。特别是编译器无法知道什么是<代码>互斥< <代码>意味着互斥操作与操作系统交互,或者它们对线程有什么影响。onized
关键字在这方面会有很大的不同。不,优化不能移除显式锁;锁有明显的副作用。我明白了。感谢您的解释。请在SO平台上提供答案。
std::mutex m;
int f()
{
    static int i = 0;
    std::lock_guard<std::mutex> lg(m);
    std::cout << i << " -> ";
    ++i;       
    std::cout << i << '\n';
    return i; 
}
//
// includes and using, omitted to simplify the example
//
void move_money_from(Cash amount, BankAccount &a, BankAccount &b) {
   //
   // suppose a mutex m within BankAccount, exposed as public
   // for the sake of simplicity
   //
   lock_guard<mutex> lckA { a.m };
   lock_guard<mutex> lckB { b.m };
   // oversimplified transaction, obviously
   if (a.withdraw(amount))
      b.deposit(amount);
}

int main() {
   BankAccount acc0{/* ... */};
   BankAccount acc1{/* ... */};
   thread th0 { [&] {
      // ...
      move_money_from(Cash{ 10'000 }, acc0, acc1);
      // ...
   } };
   thread th1 { [&] {
      // ...
      move_money_from(Cash{ 5'000 }, acc1, acc0);
      // ...
   } };
   // ...
   th0.join();
   th1.join();
}
void move_money_from(Cash amount, BankAccount &a, BankAccount &b) {
   synchronized {
      // oversimplified transaction, obviously
      if (a.withdraw(amount))
         b.deposit(amount);
   }
}