C++11 多线程编程-小白零基础到手撕线程池
终南无羡:
up你好,想问一下p7关于饿汉模式和懒汉模式是不是讲反了呀,我查到的资料说饿汉模式是类加载期间就创建好实例,懒汉模式是一开始不创建实例等有需要再创建……结合这俩模式的名字想来好像也应该是这样才对??[脸红]虽然但是并不影响总体的理解,感谢up!
【回复】你是对的,懒汉式对应的是lazy语意,需要的时候才加载。
静态局部变量就是这个方案,第一次调用的时候才进行初始化。
【回复】回复 @鹰击长空鱼浅底 :我回头看了一下视频 是我说反了 抱歉 口误
登高望远河山大好:
lamda表达式
左值引用
完美转发forward
队列queue
emplace
可变参数
模板函数
万能引用
右值引用
函数适配器bind
时间库chrono
企业太太:
有关P3 14:02的一个地方,我认为导致程序不报错的原因压根不是智能指针的问题,是因为下面的t.join问题,main函数会等待线程结束才会销毁指针,这个时候你哪怕是不传递智能指针,传递obj对象照样能运行,我觉得在这个例子里面体现不出智能指针和普通指针的区别。
【回复】是实际工程中可能会执行销毁操作,这里实例给的不是太完善
【回复】回复 @张小松丶 : ?中间什么代码都没有,主线程通过join()阻塞了,怎么释放那个对象啊,感觉这里明显讲错了..
【回复】从11:00开始看,看他说的话。 中间可能会执行很多操作,比如释放掉这个对象。
彩笔丶只手遮天:
我用的cpu只有一个核 是不是就是线程安全的了[doge]
【回复】回复 @南顺一村程序猿 : 不能
【回复】回复 @GrinRain : [脱单doge]单cpu真的能多线程?我的意思是真正意义上的多线程
实野冲萝:
这个视频用了4天看了两遍,自己还做了一份笔记,总体上来说收获还是蛮大的,至少终于懂得什么是多线程了和在c++中的使用了
【回复】祝自己和在座的各位面试顺利吧
【回复】回复 @我之有我 : 哈哈,哥们我就随便粗制滥造写的内容,没多好的,笔记这东西我都是图个自己看得懂就行。
【回复】回复 @实野冲萝 : 可以共享下笔记吗?[脱单doge]
basicQWER:
请问在第三节中,对t1和t2同时进行了join操作,那这两个线程是并行的,还是先执行完t1,在执行t2
【回复】回复 @求学的暴躁小萌 :t1 和 t2 在创建时就已经开始执行了,所以是同时在执行,t1.join 在前面还是t2.join在前面不影响,只是确保两个线程都执行完了,比如说 t1 先执行完,t2还没有执行完,那么t2.join这里就会阻塞一段时间等待执行完毕,如果t2先执行完,执行到t2.join就不阻塞直接结束
【回复】回复 @程序员陈子青 : 个人理解是:join函数的作用是阻塞主线程,子线程正常运行。只有当t1运行完成之后,主线程阻塞的原因消失了,才会正常运行主线程。不知道对不对[脱单doge]
汐入汣玖里:
第八节的时候,不会出现这种情况吗?如果消费者先加锁,然后队列为空,阻塞了;然后生产者去加锁的时候就拿不到锁了,然后也阻塞了;
【回复】队列为空时等待,等队列有的时候,就直接打开了
【回复】当前线程调用wait()后将被阻塞,直到另外某个线程调用notify_*唤醒当前线程;当线程被阻塞时,该函数会自动调用std::mutex的unlock()释放锁,使得其它被阻塞在锁竞争上的线程得以继续执行。一旦当前线程获得通知(notify,通常是另外某个线程调用notify_*唤醒了当前线程),wait()函数也是自动调用std::mutex的lock()。wait分为无条件被阻塞和带条件的被阻塞两种。
————————————————
版权声明:本文为CSDN博主「杂质想当杂志」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
【回复】Sem_wait() 条件满足 给自己的资源-1 否则阻塞
1.阻塞线程
2.阻塞时在内部实现了解锁,让其他线程可以拿到锁资源
3.解除阻塞时会有多个在wait的线程去抢锁,抢到的继续向下执行。
没抢到的继续被sem_wait();
金色道恩:
老师,请问本项目最终成品只是一个线程池吗?该线程池有哪些功能啊?
【回复】后面会介绍的,关注一下
一身轻的书与:
我是在定义静态log指针之前加了一个类的声明,但是还是报错,就把log改名了,成功运行
【回复】是的,应该加个类的声明,不然编译器不知道Log是个类,就会报错
【回复】回复 @tristansss : 给log改了个名就好了[辣眼睛]
【回复】哥们你这是版本是多少啊,为什么我没用[脸红]
张大爷有房有低保:
P7代码,照着老师的运行不起来,自己改了一下
#include <thread>
#include <mutex>
class Log
{
public:
static Log& GetInstance()
{
//static Log log; //饿汉模式
//return log;
std::call_once(once, initfunc);
return *log;
}
static void initfunc()
{
if (!log)
{
log = new Log;
}
}
void PrintLog(std::string msg)
{
std::cout << __TIME__ << " " << msg << std::endl;
}
private:
Log() {}
~Log() {}
Log(const Log&) = delete;
Log& operator=(const Log&) = delete;
//静态成员必须类外初始化
static Log* log;
static std::once_flag once;
};
Log* Log::log = nullptr;
std::once_flag Log::once;void print_error()
{
Log::GetInstance().PrintLog("error");
}
int main()
{
std::thread t1(print_error);
std::thread t2(print_error);
t1.join();
t2.join();
return 0;
}
【回复】非常有用,我也是到p7那里不知道为什么一直报错
打你DuangDuang:
大佬,P7中的代码和您的一样,为什么我的static Log& GetInstance()函数return *log;里的log报错和static void init()函数里的if (!log) log = new Log两个log报错@程序员陈子青 提示是log不明确,代码检查了好几遍,完全一模一样额……
【回复】在定义指针log前,先class Log;加个类的声明
【回复】类的静态成员函数需要在类外初始化才会被创建。
Kasaki霙:
这样简洁明了讲知识的视频 必须给个三连
鲁米的诗:
老师讲的真好特别是常见错误那一章节帮助很大[打call]坐等更新[doge]
山道年77:
关于生产者和消费者的代码,是不是设计得有问题了?如果是消费者线程先持有的锁,那它就一直阻塞在等待队列不为空了吧,然后生产者线程又没有持有锁就又不能往任务队列里放东西,这是不是死锁了
凯旋゜:
写的两种都是懒汉模式,静态全局变量C++11以上已经没有线程安全问题了,是官方最推荐的写法。