【问题标题】:Unexpected behavior with mutex::try_lock()mutex::try_lock() 的意外行为
【发布时间】:2018-04-23 17:08:58
【问题描述】:

我在一个程序中尝试了 mutex::try_lock() 成员,它执行以下操作:

1) 它故意将互斥锁锁定在并行线程中。
2) 在主线程中,它尝试使用 try_lock() 锁定互斥锁。
a) 如果没有获得锁,它会将字符添加到字符串中。
b) 获取锁后,打印字符串。

我已经在 2 个在线编译器上测试了这个程序:

1) 在 coliru(其 thread::hardware_concurrency() 为 1)上,程序为 here:

int main()
{
   /// Lock the mutex for 1 nanosecond.
   thread t {lock_mutex};

   job();

   t.join();
}


/// Lock the mutex for 1 nanosecond.
void lock_mutex()
{
   m.lock();

   this_thread::sleep_for(nanoseconds {1});

   m.unlock();
}


void job()
{
   cout << "starting job ..." << endl;

   int lock_attempts {};

   /// Try to lock the mutex.
   while (!m.try_lock())
   {
      ++lock_attempts;

      /// Lock not acquired.
      /// Append characters to the string.
      append();
   }

   /// Unlock the mutex.
   m.unlock();

   cout << "lock attempts = " << lock_attempts
        << endl;

   /// Lock acquired.
   /// Print the string.
   print();
}


/// Append characters to the string
void append()
{
   static int count = 0;

   s.push_back('a');

   /// For every 5 characters appended,
   /// append a space.
   if (++count == 5)
   {
      count = 0;
      s.push_back(' ');
   }
}


/// Print the string.
void print()
{
   cout << s << endl;
}


这里,程序输出如预期:

starting job ...

lock attempts = 2444

aaaaa aaaaa aaaaa ...


但是,在这里,如果我从程序中删除以下语句:

   cout << "starting job ..." << endl;

输出显示:

   lock attempts = 0

为什么会这样?


2) 另一方面,当我在 ideone 上尝试这个程序(甚至锁定 1 秒而不是 1 纳秒)时 - here - 我总是得到一个输出显示:

   lock attempts = 0

即使程序中存在诊断“启动作业”,也会发生这种情况。

ideone 的 thread::hardware_concurrency() 为 8。

也就是说,我立即成功获得了锁。为什么会这样?

请注意,这不是 try_lock() 虚假失败的情况。在这种情况下,虽然在互斥体上没有个现有锁,但成员返回 false,表示锁定尝试不成功。

在这里,相反的情况似乎正在发生。尽管互斥体上存在锁(显然),但成员返回 true,表示已成功获取新锁!为什么?

【问题讨论】:

  • 您的代码中没有任何内容可以保证生成的线程将在job 开始执行之前运行。所以这可能会发生(有些时候,大多数时候,总是,没人能猜到)。
  • "但是,如果我删除" 好吧,这表明已经发生了什么:使用该语句,您的主线程在获取锁方面比其他线程慢,没有它会更快...如果您只想尝试功能,请执行以下操作:让创建的线程锁定 2 秒,并让主线程在线程创建后休眠 1 秒。然后你观察到的行为仍然发生的概率变得如此接近于你可以忽略它......

标签: c++ multithreading


【解决方案1】:

使用 std::endl 调用 cout.operator

【讨论】:

    猜你喜欢
    • 2021-04-25
    • 2018-06-26
    • 2016-05-21
    • 2020-10-04
    • 2016-07-16
    • 2016-05-10
    • 2020-07-23
    • 2021-08-23
    • 2021-11-16
    相关资源
    最近更新 更多