C++同步定时等待
C++ Synchronization timed wait
我有一个多线程 C++ 应用程序。我想用 busy/free 状态标记一个对象,例如:
- 线程可以切换对象的状态
- 线程必须随时独占访问某些 public 成员函数(而其他 public 成员函数不需要同步)
- 如果对象正忙,线程可以选择无限等待或等待一段定义的时间,直到对象空闲。
我实现了下面的要求,有更好的方法吗?
#include <condition_variable>
#include <mutex>
#include <atomic>
#include <thread>
#include <iostream>
std::mutex m_Mutex;
std::condition_variable m_ConditionVariable;
std::atomic_flag m_BusyFlag;
const int TRY_LOCK_TIMEOUT_MILLIS = 1;
bool IsFree() { return !m_BusyFlag.test_and_set(); }
bool LockSeqNum(bool timed_wait)
{
std::cout <<" TRY LockSeqNum, thread= " << std::this_thread::get_id() << endl;
bool success = true;
std::unique_lock<std::mutex> lck(m_Mutex);
if (m_BusyFlag.test_and_set())
{
if (timed_wait)
success = !m_ConditionVariable.wait_for(lck, std::chrono::milliseconds(TRY_LOCK_TIMEOUT_MILLIS), [] { return IsFree(); });
else
m_ConditionVariable.wait(lck, [] { return IsFree(); });
}
std::cout << "LockSeqNum " << success << " thread = " << std::this_thread::get_id() << endl;
return success;
}
void UnlockSeqNum()
{
std::cout << " UNLockSeqNum, thread= " << std::this_thread::get_id() << endl;
std::unique_lock<std::mutex> lck(m_Mutex);
m_BusyFlag.clear();
m_ConditionVariable.notify_one();
}
如果你想允许 IsFree()
的外部,代码就可以了。否则,正如 Yakk 在评论中指出的那样,将 m_BusyFlag
声明为简单布尔值就足够了。 atomic_flag
在那里是开销,因为变量总是在互斥锁下访问。
您拥有使用条件等待所需的最少工具:条件变量、互斥锁和用于等待其状态的普通变量。因此,只有当线程需要调用 UnlockSeqNum
时,才可能实现更简单的实现(简单锁定),该线程之前调用过 LockSeqNum。
我有一个多线程 C++ 应用程序。我想用 busy/free 状态标记一个对象,例如:
- 线程可以切换对象的状态
- 线程必须随时独占访问某些 public 成员函数(而其他 public 成员函数不需要同步)
- 如果对象正忙,线程可以选择无限等待或等待一段定义的时间,直到对象空闲。
我实现了下面的要求,有更好的方法吗?
#include <condition_variable>
#include <mutex>
#include <atomic>
#include <thread>
#include <iostream>
std::mutex m_Mutex;
std::condition_variable m_ConditionVariable;
std::atomic_flag m_BusyFlag;
const int TRY_LOCK_TIMEOUT_MILLIS = 1;
bool IsFree() { return !m_BusyFlag.test_and_set(); }
bool LockSeqNum(bool timed_wait)
{
std::cout <<" TRY LockSeqNum, thread= " << std::this_thread::get_id() << endl;
bool success = true;
std::unique_lock<std::mutex> lck(m_Mutex);
if (m_BusyFlag.test_and_set())
{
if (timed_wait)
success = !m_ConditionVariable.wait_for(lck, std::chrono::milliseconds(TRY_LOCK_TIMEOUT_MILLIS), [] { return IsFree(); });
else
m_ConditionVariable.wait(lck, [] { return IsFree(); });
}
std::cout << "LockSeqNum " << success << " thread = " << std::this_thread::get_id() << endl;
return success;
}
void UnlockSeqNum()
{
std::cout << " UNLockSeqNum, thread= " << std::this_thread::get_id() << endl;
std::unique_lock<std::mutex> lck(m_Mutex);
m_BusyFlag.clear();
m_ConditionVariable.notify_one();
}
如果你想允许 IsFree()
的外部,代码就可以了。否则,正如 Yakk 在评论中指出的那样,将 m_BusyFlag
声明为简单布尔值就足够了。 atomic_flag
在那里是开销,因为变量总是在互斥锁下访问。
您拥有使用条件等待所需的最少工具:条件变量、互斥锁和用于等待其状态的普通变量。因此,只有当线程需要调用 UnlockSeqNum
时,才可能实现更简单的实现(简单锁定),该线程之前调用过 LockSeqNum。