这是一个有效的二进制互斥实现吗?
Is this a valid binary mutex implementation?
我不太确定这类问题是否会在这里遭到拒绝,但 是 当我有问题时我首先会来的地方,所以,我们开始了。
我有一个 std::vector<T> v
用来存储数据。在线程t1
中,有一个数据生成器,可以随时插入数据。另一方面,在线程 t2
中,我需要在任意时间搜索 v
并从中访问和 return 一个元素。删除、交换等保证不会发生在v
上,直到t1
和t2
都加入主线程。
没有任何线程安全措施,代码以 SIGABRT
退出。我首先使用 std::mutex
和 std::lock_guard
并成功了,但是 lock/unlocks 的数量以百万计,我希望加快速度。所以我尝试实现以下系统:
#include <atomic>
#include <cassert>
#include <thread>
// Mutex-like thingy begin
class MyMutex
{
private:
std::atomic<bool> modifyLockRequest;
std::atomic<bool> accessLockRequest;
std::atomic<bool> accessLock;
public:
MyMutex() :
modifyLockRequest(false),
accessLockRequest(false),
accessLock(false) {}
void acquireModifyLock() {
assert(!modifyLockRequest);
modifyLockRequest = true;
while( accessLockRequest && accessLock ) {
std::this_thread::yield();
}
}
void releaseModifyLock() {
assert(modifyLockRequest);
modifyLockRequest = false;
}
void acquireAccessLock() {
assert(!accessLockRequest);
accessLockRequest = true;
while (modifyLockRequest) {
std::this_thread::yield();
}
accessLock = true;
}
void releaseAccessLock() {
assert(accessLockRequest);
accessLock = false;
accessLockRequest = false;
}
};
MyMutex myMutex;
然后我用这个
myMutex.acquireModifyLock();
// Do insertion/deletion etc. on `v`
myMutex.releaseModifyLock();
和
myMutex.acquireAccessLock();
// Do stuff with `v[i]`
myMutex.releaseAccessLock();
我的理由是有 2 个布尔标志来警告任何线程试图获取锁,并有第三个标志来中断两个线程同时尝试获取锁的情况。
此代码似乎在 std::mutex
和 std::lock_guard
双人组的大约 1/8 时间运行良好,但是,我的问题是,此解决方案是否 得到保证 到 总是 在我只有 2 个线程的情况下工作?
使用 std::atomic_flag
实现自旋锁在过去 3 个月内运行良好。此外,由于我的实现没有原子测试和设置机制,我会说,NO,它不是有效的(线程安全的)实现。感谢 Igor Tandetnik 的建议。
我不太确定这类问题是否会在这里遭到拒绝,但 是 当我有问题时我首先会来的地方,所以,我们开始了。
我有一个 std::vector<T> v
用来存储数据。在线程t1
中,有一个数据生成器,可以随时插入数据。另一方面,在线程 t2
中,我需要在任意时间搜索 v
并从中访问和 return 一个元素。删除、交换等保证不会发生在v
上,直到t1
和t2
都加入主线程。
没有任何线程安全措施,代码以 SIGABRT
退出。我首先使用 std::mutex
和 std::lock_guard
并成功了,但是 lock/unlocks 的数量以百万计,我希望加快速度。所以我尝试实现以下系统:
#include <atomic>
#include <cassert>
#include <thread>
// Mutex-like thingy begin
class MyMutex
{
private:
std::atomic<bool> modifyLockRequest;
std::atomic<bool> accessLockRequest;
std::atomic<bool> accessLock;
public:
MyMutex() :
modifyLockRequest(false),
accessLockRequest(false),
accessLock(false) {}
void acquireModifyLock() {
assert(!modifyLockRequest);
modifyLockRequest = true;
while( accessLockRequest && accessLock ) {
std::this_thread::yield();
}
}
void releaseModifyLock() {
assert(modifyLockRequest);
modifyLockRequest = false;
}
void acquireAccessLock() {
assert(!accessLockRequest);
accessLockRequest = true;
while (modifyLockRequest) {
std::this_thread::yield();
}
accessLock = true;
}
void releaseAccessLock() {
assert(accessLockRequest);
accessLock = false;
accessLockRequest = false;
}
};
MyMutex myMutex;
然后我用这个
myMutex.acquireModifyLock();
// Do insertion/deletion etc. on `v`
myMutex.releaseModifyLock();
和
myMutex.acquireAccessLock();
// Do stuff with `v[i]`
myMutex.releaseAccessLock();
我的理由是有 2 个布尔标志来警告任何线程试图获取锁,并有第三个标志来中断两个线程同时尝试获取锁的情况。
此代码似乎在 std::mutex
和 std::lock_guard
双人组的大约 1/8 时间运行良好,但是,我的问题是,此解决方案是否 得到保证 到 总是 在我只有 2 个线程的情况下工作?
使用 std::atomic_flag
实现自旋锁在过去 3 个月内运行良好。此外,由于我的实现没有原子测试和设置机制,我会说,NO,它不是有效的(线程安全的)实现。感谢 Igor Tandetnik 的建议。