[多线程]多线程编程需要注意的问题|多进程
多线程三个经典问题
https://blog.csdn.net/lisonglisonglisong/article/details/45390227
可重入函数与不可重入函数
保证函数的可重入性的方法:
1)在写函数时候尽量使用局部变量(例如寄存器、堆栈中的变量);
2)对于要使用的全局变量要加以保护(如采取关中断、信号量等互斥方法),这样构成的函数就一定是一个可重入的函数。
满足下列条件的函数多数是不可重入(不安全)的:
1)函数体内使用了静态的数据结构;
2)函数体内调用了malloc() 或者 free() 函数;
3)函数体内调用了标准 I/O 函数。
如何将一个不可重入的函数改写成可重入函数呢?
1)不要使用全局变量。因为别的代码很可能改变这些变量值。
2)在和硬件发生交互的时候,切记执行类似 disinterrupt() 之类的操作,就是关闭硬件中断。完成交互记得打开中断,在有些系列上,这叫做“进入/ 退出核心”。
3)不能调用其它任何不可重入的函数。
4)谨慎使用堆栈。
浅谈可重入函数与不可重入函数【转】_shareinfo2018-CSDN博客_可重入函数
fork()的子进程和父进程有什么不同,子进程可以从父进程那里能够继承什么,又不能继承什么
《UNIX系统编程》第24章进程的创建
fork之后父子进程同时从fork点开始执行、
父子进程共享代码抄段,数据段都是完全拷贝,相互之间的更改zhidao不会影响。
(fork之后exec之前两个进程用的是相同的物理空间(内存区),子进程的代码段、数据段、堆栈都是指向父进程的物理空间,也就是说,两者的虚拟空间不同,但其对应的物理空间是同一个。)
但是值得注意的是socket是共享的
互斥锁
std::mutex mu;
// 使用锁保护
void shared_print(string msg, int id) {
mu.lock(); // 上锁
cout << msg << id << endl;
mu.unlock(); // 解锁
}
有一个隐藏着的问题,如果mu.lock()
和mu.unlock()
之间的语句发生了异常,会发生什么?unlock()
语句没有机会执行!导致导致mu
一直处于锁着的状态,其他使用shared_print()
函数的线程就会阻塞。
void shared_print(string msg, int id) {
//构造的时候帮忙上锁,析构的时候释放锁
std::lock_guard<std::mutex> guard(mu);
//mu.lock(); // 上锁
cout << msg << id << endl;
//mu.unlock(); // 解锁
}
RAII
技术,即获取资源即初始化(Resource Acquisition Is Initialization)技术,这是c++
中管理资源的常用方式。 //构造的时候帮忙上锁,(函数退出)析构的时候释放锁
join的必要:
举个例子,现在有 A, B, C 三件事情,只有做完 A 和 B 才能去做 C,而 A 和 B 可以并行完成。
int main(){
thread t = new thread(A);
B(); // 此时 A 与 B 并行进行
t.join(); // 确保 A 完成
C();
}