【 std::allocator】
标准库中包含一个名为allocator的类,允许我们将分配和初始化分离。使用allocator通常会提供更好的性能和更灵活的内存管理能力。
标准库allocator类定义在头文件memory中,它帮助我们将内存分配和对象构造分离开来。它提供一种类型感知的内存分配方法,它分配的内存是原始的、未构造的。
allocator支持的操作,如下:
下面是一段标准用法:
int test_allocator_1()
{
std::allocatorstring> alloc; // 可以分配string的allocator对象
int n{ 5 };
auto const p = alloc.allocate(n); // 分配n个未初始化的string
auto q = p; // q指向最后构造的元素之后的位置
alloc.construct(q++); // *q为空字符串
alloc.construct(q++, 10, 'c'); // *q为cccccccccc
alloc.construct(q++, "hi"); // *q为hi
std::cout << *p << std::endl; // 正确:使用string的输出运算符
//std::cout << *q << std::endl; // 灾难:q指向未构造的内存
std::cout << p[0] << std::endl;
std::cout << p[1] << std::endl;
std::cout << p[2] << std::endl;
while (q != p) {
alloc.destroy(--q); // 释放我们真正构造的string
}
alloc.deallocate(p, n);
return 0;
}
参考:
1、https://blog.csdn.net/fengbingchun/article/details/78943527
【 std::recursive_mutex】
定义于头文件
class recursive_mutex; // C++11 起
recursive_mutex
类是同步原语,能用于保护共享数据免受从个多线程同时访问。
recursive_mutex
提供排他性递归所有权语义:
- 调用方线程在从它成功调用
lock
或try_lock
开始的时期里 占有recursive_mutex
。此时期间,线程可以进行对lock
或try_lock
的附加调用。所有权的时期在线程调用unlock
匹配次数时结束。 - 线程占有
recursive_mutex
时,若其他所有线程试图要求recursive_mutex
的所有权,则它们将阻塞(对于调用lock
)或收到false 返回值(对于调用try_lock
)。 - 可锁定
recursive_mutex
次数的最大值是未指定的,但抵达该数后,对lock
的调用将抛出std::system_error 而对try_lock
的调用将返回 false 。
若 recursive_mutex
在仍为某线程占有时被销毁,则程序行为未定义。 recursive_mutex
类满足互斥 (Mutex) 和标准布局类型(StandardLayoutType) 的所有要求。
参考:
1、https://zh.cppreference.com/w/cpp/thread/recursive_mutex
【 std::condition_variable】
#include // std::condition_variable
std::mutex mtx; // 全局互斥锁.
std::condition_variable cv; // 全局条件变量.
bool ready = false; // 全局标志位.
void do_print_id(int id)
{
std::unique_lock lck(mtx);
while (!ready) // 如果标志位不为 true, 则等待...
cv.wait(lck); // 当前线程被阻塞, 当全局标志位变为 true 之后,
// 线程被唤醒, 继续往下执行打印线程编号id.
std::cout << "thread " << id << '\n';
}
void go()
{
std::unique_lock lck(mtx);
ready = true; // 设置全局标志位为 true.
cv.notify_all(); // 唤醒所有线程.
}
int main()
{
std::thread threads[10];
// spawn 10 threads:
for (int i = 0; i < 10; ++i)
threads[i] = std::thread(do_print_id, i);
std::cout << "10 threads ready to race...\n";
go(); // go!
for (auto & th:threads)
th.join();
return 0;
}
第一种情况下,在线程被阻塞时,该函数会自动调用 lck.unlock() 释放锁,使得其他被阻塞在锁竞争上的线程得以继续执行。
另外,一旦当前线程获得通知(notified,通常是另外某个线程调用 notify_* 唤醒了当前线程),wait() 函数也是自动调用 lck.lock(),使得 lck 的状态和 wait 函数被调用时相同。
在第二种情况下(即设置了 Predicate),pred 相当于资源数量。只有当 pred 条件为 false 时调用 wait() 才会阻塞当前线程,并且在收到其他线程的通知后只有当 pred 为 true 时才会被解除阻塞。
#include // std::condition_variable
std::mutex mtx;
std::condition_variable cv;
int cargo = 0;
bool shipment_available()
{
return cargo != 0;
}
// 消费者线程.
void consume(int n)
{
for (int i = 0; i < n; ++i) {
std::unique_lock lck(mtx);
cv.wait(lck, shipment_available);
std::cout << cargo << '\n';
cargo = 0;
}
}
int main()
{
std::thread consumer_thread(consume, 10); // 消费者线程.
// 主线程为生产者线程, 生产 10 个物品.
for (int i = 0; i < 10; ++i) {
while (shipment_available())
std::this_thread::yield();
std::unique_lock lck(mtx);
cargo = i + 1;
cv.notify_one();
}
consumer_thread.join();
return 0;
}
std::condition_variable_any 介绍
与 std::condition_variable 类似,只不过 std::condition_variable_any 的 wait 函数可以接受任何 lockable 参数,而 std::condition_variable 只能接受 std::unique_lock
参考:
1、https://www.cnblogs.com/haippy/p/3252041.html
Original: https://www.cnblogs.com/tekkaman/p/10313882.html
Author: Tekkaman
Title: 一些常用的 std 类型
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/549340/
转载文章受原作者版权保护。转载请注明原作者出处!