在 Boost 中实现旋转锁.需要示例
Implementing a spinlock in Boost. Example Needed
我想知道boost是否有任何有助于实现旋转锁的库。我知道 boost 支持互斥锁,但我找不到任何显示或描述 boost 中的自旋锁的示例。任何显示如何使用 boost(最好)实现旋转锁定的示例将不胜感激。(C++98)
使用 Boost.Atomic
的示例:
#include <boost/atomic.hpp>
class SpinLock
{
boost::atomic_flag flag; // it differs from std::atomic_flag a bit -
// does not require ATOMIC_FLAG_INIT
public:
void lock()
{
while( flag.test_and_set(boost::memory_order_acquire) )
;
}
bool try_lock()
{
return !flag.test_and_set(boost::memory_order_acquire);
}
void unlock()
{
flag.clear(boost::memory_order_release);
}
};
科里鲁现场演示
#include <boost/range/algorithm.hpp>
#include <boost/atomic.hpp>
#include <boost/thread.hpp>
#include <iostream>
#include <vector>
class SpinLock
{
boost::atomic_flag flag;
public:
void lock()
{
while( flag.test_and_set(boost::memory_order_acquire) )
;
}
bool try_lock()
{
return !flag.test_and_set(boost::memory_order_acquire);
}
void unlock()
{
flag.clear(boost::memory_order_release);
}
};
int main()
{
using namespace std; using namespace boost;
SpinLock lock;
vector<thread> v;
for(auto i = 0; i!=4; ++i)
v.emplace_back([&lock, i]
{
for(auto j = 0; j!=16; ++j)
{
this_thread::yield();
lock_guard<SpinLock> x(lock);
cout << "Hello from " << i << flush << "tj = " << j << endl;
}
});
for(auto &t: v)
t.join();
}
输出为:
Hello from 0 j = 0
Hello from 1 j = 0
Hello from 3 j = 0
Hello from 2 j = 0
Hello from 3 j = 1
Hello from 1 j = 1
Hello from 3 j = 2
Hello from 2 j = 1
Hello from 1 j = 2
Hello from 2 j = 2
Hello from 1 j = 3
Hello from 2 j = 3
Hello from 1 j = 4
Hello from 3 j = 3
Hello from 2 j = 4
Hello from 1 j = 5
Hello from 2 j = 5
Hello from 1 j = 6
Hello from 2 j = 6
Hello from 1 j = 7
Hello from 2 j = 7
Hello from 1 j = 8
Hello from 2 j = 8
Hello from 3 j = 4
Hello from 2 j = 9
Hello from 3 j = 5
Hello from 1 j = 9
Hello from 2 j = 10
Hello from 1 j = 10
Hello from 2 j = 11
Hello from 3 j = 6
Hello from 1 j = 11
Hello from 2 j = 12
Hello from 3 j = 7
Hello from 1 j = 12
Hello from 2 j = 13
Hello from 3 j = 8
Hello from 2 j = 14
Hello from 3 j = 9
Hello from 1 j = 13
Hello from 2 j = 15
Hello from 1 j = 14
Hello from 3 j = 10
Hello from 1 j = 15
Hello from 3 j = 11
Hello from 3 j = 12
Hello from 3 j = 13
Hello from 3 j = 14
Hello from 3 j = 15
Hello from 0 j = 1
Hello from 0 j = 2
Hello from 0 j = 3
Hello from 0 j = 4
Hello from 0 j = 5
Hello from 0 j = 6
Hello from 0 j = 7
Hello from 0 j = 8
Hello from 0 j = 9
Hello from 0 j = 10
Hello from 0 j = 11
Hello from 0 j = 12
Hello from 0 j = 13
Hello from 0 j = 14
Hello from 0 j = 15
下面是
使用 C++11 原子的示例:
#include <atomic>
typedef std::atomic<bool> Lock;
void enterCritical(Lock& lock) {
bool unlocked = false;
while (!lock.compare_exchange_weak(unlocked, true));
}
void exitCritical(Lock& lock) {
lock.store(false);
}
The spinlock solution provided by erenon sometimes generated crumble cout result. but the boost::mutext solution won't. So either the solution is incorrect, or my understanding of cout is wrong.
#include <iostream>
#include <thread>
#include <atomic>
#include <boost/thread/mutex.hpp>
using namespace std;
class spinlock {
private:
std::atomic<bool> lock_;
public:
spinlock() {
lock_.store(false);
}
void lock() {
bool unlocked = false;
while (!lock_.compare_exchange_weak(unlocked, true));
}
void unlock() {
lock_.store(false);
}
};
class add_one
{
private:
std::string name_;
unsigned int& num_;
spinlock & lock_;
boost::mutex & mutex_;
public:
add_one(std::string name, unsigned int& num, spinlock &lock, boost::mutex &mutex)
:name_(name),
num_(num),
lock_(lock),
mutex_(mutex)
{
}
void add_and_display()
{
while(true)
{
lock_.lock();
//boost::lock_guard<boost::mutex> g( mutex_);
std::cout << name_ << " " << num_ << endl;
if(num_ == 10000000)
{
return;
}
num_++;
lock_.unlock();
}
}
};
int main()
{
cout << "Hello World" << endl;
unsigned int n = 0;
spinlock lock;
boost::mutex mutex;
add_one one("t1", n ,lock, mutex);
add_one two("t2", n ,lock, mutex);
add_one three("t3", n ,lock, mutex);
//add_one four("t4", n ,lock, mutex);
std::thread t1(std::bind(&add_one::add_and_display, one));
std::thread t2(std::bind(&add_one::add_and_display, two));
std::thread t3(std::bind(&add_one::add_and_display, three));
//std::thread t4(std::bind(&add_one::add_and_display, four));
t1.join();
t2.join();
t3.join();
//t4.join();
return 0;
}
有点偏离主题但相关 - 可以使用 C++11(而不是 C++03)获得无锁保证的旋转锁,而无需
boost
(尽管这是问题标题)。
使用 C++11 std::atomic_flag
.
它始终是无锁的,正如叶夫根尼·帕纳修克在 erenon 的答案评论中指出的那样。 std::atomic
似乎不能保证无需等待(在某些情况下是必需的)。
也符合BasicLockable
接口,可供std::lock_guard
/std::scoped_lock
/...
class Spinlock {
std::atomic_flag _lock = ATOMIC_FLAG_INIT;
public:
void lock() {
while (_lock.test_and_set(std::memory_order_acquire)) continue;
}
void unlock() {
_lock.clear(std::memory_order_release);
}
};
相关文章:
- 理解boost::asio-async_read在无需读取内容时的行为
- boost::进程间消息队列引发错误
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- cmake如何在fedora工作站中找到boost静态库包
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- 与互斥锁相比,旋转锁可以保证上下文切换
- Boost Graph Library,修复节点大小
- 什么是"#include <boost/functional/hash.hpp> "?
- 基于boost的程序的静态链接——zlib问题
- C++:如何在CLion IDE中安装Boost
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 如何在boost beast http请求中设置http头
- Boost Spirit,获取迭代器内部语义动作
- boost::asio::steady_timer()与sleep()我应该使用哪一个
- boost.log-如何用附加和旋转配置text_file_backend
- BOOST ::日志是每次运行应用程序时都可能旋转文件
- 指定使用STD ::旋转不是从Boost旋转
- Boost通过旋转记录多个文件
- 在 Boost 中实现旋转锁.需要示例
- boost::几何多边形的 outer() 在多边形旋转后有错误的坐标