C++多线程编程

Last edited time
Sep 17, 2024 10:58 AM
AI summary
C++多线程编程涉及线程同步机制,主要使用锁机制来解决资源竞争问题。死锁的四个必要条件包括互斥、请求与保持、不剥夺和循环等待,避免死锁需合理规划资源分配。创建线程需包含<thread>库,并使用join()detach()函数管理线程。注意事项包括Windows编译问题和cout的线程安全性。
Last edited by
Tags
版本:11、14、17、20

线程同步机制

线程并发执行
线程资源竞争导致资源不同步,最基本的同步机制是锁机制。
锁的获取和释放:上锁和解锁
C++、Go采用mutex互斥锁
Java采用synchronized关键字对某些对象上锁
频繁上锁和解锁低效的改进方法:在线程中创建一个临时变量做计算,然后再将最终的结果累加到全局的共享变量中。这样只有最后一个线程执行需要同步,其他的都可以并发执行。
多个锁的嵌套使用会导致线程死锁现象。考虑线程的上锁顺序,可以避免线程死锁现象。
产生死锁的四个必要条件
  • 互斥条件:一个资源每次只能被一个进程使用。
  • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
  • 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
  • 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
如何解决死锁?
在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源,这就是避免、预防和解决死锁的最佳实践。此外,也要防止进程在处于等待状态的情况下占用资源。因此,对资源的分配要给予合理的规划。
 
部分语言支持的atomic操作,比锁效率更高。
C++线程创建的过程
  1. 多线程的库:#include <thread>
  1. 创建线程:调用thread类去创建一个线程对象
    1. 注意点:创建一个线程,不做处理 会调用abort函数中止程序,一个线程只能join一次,重复join会引发中断
  1. join()函数 加入,汇合线程,阻塞主线程,等待子线程执行结束,才会回到主线程中
  1. detach()函数 分离,打破依赖关系,把子线程驻留后台
    1. 当前从detach后,就不能够再join
  1. joinable() 判断当前线程是否可以做join或者detach过程,可以返回true,不可以返回false
其他创建线程的方法
  1. 普通函数方式(上面)
  1. 类和对象
  1. C++ lambda表达式创建线程
  1. 带参的方式创建线程
  1. 带智能指针创建线程
  1. 类的成员函数创建线程
 

多线程编程注意事项

Windows编译常见问题:MinGW编译报错找不到thread头文件解决方法:
需要采用posix的而不是win32的thread版本
注意:cout不是线程安全的,默认可能不会输出结果
VSCode调试报错:Unable to start debugging. Unexpected GDB output from command
该问题导致代码中使用多线程函数后,终端无任何输出
原因:DLL冲突
参考如下链接解决:
Loading...