5前言
作者:小蜗牛向前冲
名言:我可以接受失败,但我不能接受放弃
如果觉的博主的文章还不错的话,还请
点赞,收藏,关注👀支持博主。如果发现有问题的地方欢迎❀大家在评论区指正
分享常见的面试手撕题目(未完待续)
一、场景设计题目
1、设计一个多线程下安全缓冲区
支持push:当缓冲区满了应该阻塞等待
支持pop:移除缓冲区的元素
支持size:缓冲区中有多少有效元素
支持多个生产者和消费者同时访问,要保证线程安全
对于多线程中的安全机制:以上可以通过muetx,condition_variable实现
#include<iostream>
#include<queue>
#include<mutex>
#include<condition_variable>
using namespace std;
template<class T>
class buffer
{
public:
buffer(int capacity)
:_capacity(capacity)
{
}
void push(const T& item)
{
//加锁保证线程安全
unique_lock<mutex> lock(_mutex);
//等待直到可用空间
//wait的参数:lck锁,pred:是一个可调用对象或者函数,返回true就是不等待继续往后执行
cond_producer.wait(lock, [this]() {return _buf.size() < _capacity; });
//插入元素
_buf.push(item);
//通知消费者可以进行消费
cond_consumer.notify_one();//这里的notify_one可以让条件变量阻塞的那个线程运行起来
}
//这里返回的是队头元素
T pop()
{
//加锁
unique_lock<mutex> lock(_mutex);
//等待可以消费的元素
cond_consumer.wait(lock, [this]() {return !_buf.empty(); });
T item = _buf.front();
_buf.pop();
//通知生产者进行生产
cond_producer.notify_one();
return item;
}
int size()
{
return _buf.size();
}
private:
queue<T> _buf;//缓冲区
int _capacity;//容量
mutex _mutex;//锁
condition_variable cond_producer;//生产者等待条件
condition_variable cond_consumer;//消费者等待条件
};
unique_lock
和 lock_guard
的区别
-
std::lock_guard<mutex>
:- 是一个简单的、轻量级的锁管理器,一旦构造,就立即获取锁,并在析构时自动释放锁。
- 它的使用非常简单,适合不需要改变锁状态(如手动锁定、解锁)的情况。
lock_guard
不支持手动解锁或重新锁定,也不支持条件变量等待时的锁管理。
-
std::unique_lock<mutex>
:- 提供了更灵活的锁管理功能,可以手动锁定、解锁和重新锁定。
- 支持条件变量的等待机制(如
std::condition_variable::wait
)。 - 可以延迟锁定(即在构造时不立即获取锁),更适合需要更复杂锁控制的场景。
在有条件变量的情况下应该选择:unique_lock,支持手动加锁和解锁。
2、在Linux中计算一个目录的文件大小
int get_dir_size(const char *name)函数如何设计
要想知道一个文件大大小,
首先我们得打开这个文件opendir
DIR *opendir(const char *name);
返回值:
成功时:
opendir()
返回一个指向DIR
类型的指针。这个指针代表了打开的目录流,它可以被后续的readdir()
等函数使用来遍历目录内容。失败时:
opendir()
返回NULL
,并且设置全局变量errno
来指示失败的原因。例如,目录不存在、没有权限读取等原因会导致opendir()
失败
其次我们用readdir读取目录中的每个文件信息
struct dirent *readdir(DIR *dirp);
struct dirent
结构体 :
readdir()
返回的 struct dirent
结构体包含关于目录项的信息,以下是它的典型定义:
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file */
char d_name[256]; /* filename (null-terminated) */
};
这里我们关注的在目录中,我们现在读取到的文件名
最后我们还知道,每个文件在状态stat函数。
int stat(const char *pathname, struct stat *statbuf);
stat函数会讲目标路径pathname,的信息存放着statbuf结构体中
struct stat