class AtomicLock
{
std::atomic_flag flag;
public:
void lock() {
while (flag.test_and_set(std::memory_order_acquire))
flag.wait(true, std::memory_order_acquire);
}
void unlock() {
flag.clear(std::memory_order_release);
flag.notify_one();
}
};
class ThreadAtomicLock
{
static std::atomic_long id_generator;
std::atomic<long> owner_thread = -1;
static long get_id() {
thread_local auto id = id_generator++;
return id;
}
public:
void lock() {
long expected = -1;
while (!owner_thread.compare_exchange_weak(expected, get_id(), std::memory_order_acquire)) {
owner_thread.wait(expected, std::memory_order_acquire);
expected = -1;
}
}
void unlock() {
long expected = get_id();
assert (
owner_thread.compare_exchange_strong(expected, -1, std::memory_order_release) &&
"unlock of unowned lock"
);
owner_thread.notify_one();
}
};
std::atomic_long ThreadAtomicLock::id_generator = 0;
void testAtomicLock() {
std::vector<std::thread> threads;
std::atomic<bool> flag = false;
// AtomicLock lock;
ThreadAtomicLock lock;
for (int i = 0; i < 100; i++) {
threads.emplace_back([&] {
while (!flag.load(std::memory_order_acquire));
lock.lock();
std::cout << "Hello";
std::cout << " from thread ";
std::cout << std::this_thread::get_id() << " ";
int n = 10;
while (n--) std::cout << "=";
std::cout << "\n";
lock.unlock();
});
}
flag.store(true, std::memory_order_release);
for (auto& t : threads) t.join();
}
提供的AtomicLock
类可以工作,但我意识到这将允许任何线程解锁,即使它不拥有该锁。
该类ThreadAtomicLock
是为了确保只有所有者线程才能解锁而进行的尝试。
虽然它工作正常,但我怀疑这是否是实现锁所需的全部。这种实现正确吗?可以放宽一些限制吗?
我可以在解锁功能中
compare_exchange_strong
替换吗?compare_exchange_weak
这里的 ID 生成机制为每个线程存储一个额外的 ID,并执行原子操作为每个线程生成一个 ID。虽然微不足道,但我很好奇是否有更好的实现方法。
可以在锁定函数中的调用
memory_order_relaxed
中使用wait
,因为此时我们不需要进一步同步?