
Linux —— 线程互斥
发布日期:2025-04-06 08:16:17
浏览次数:6
分类:精选文章
本文共 3872 字,大约阅读时间需要 12 分钟。
Linux 线程互斥
线程封装
为了简化 POSIX 线程 (pthread) 的使用,我们可以自定义一个线程封装类 MyThread
。该类通过提供线程的启动和控制功能,使得线程的创建更加面向对象和便捷。
类定义
class MyThread { public: MyThread(pthread_t tid, const std::string &name, func_t func) : _tid(tid), _name(name), _isrunning(false), _fun(func) { std::cout << "My tid is " << _tid << " name is " << _name << std::endl; } ~MyThread() {} // 孤立 static void *ThreadRoutine(void *args) { MyThread *th = static_cast(args); th->_fun(); return nullptr; } void Start() { int retValue = pthread_create(&_tid, nullptr, ThreadRoutine, this); if (retValue != 0) { std::cout << "Create thread failed! Error code: " << retValue << std::endl; return; } else { _isrunning = true; std::cout << "Thread started successfully." << std::endl; } } void Join() { if (!_isrunning) return; int retValue = pthread_join(_tid, nullptr); if (retValue == 0) { _isrunning = false; } else { std::cout << "Join failed! Error code: " << retValue << std::endl; } } private: pthread_t _tid; std::string _name; bool _isrunning; func_t _fun;};
使用例子
#include "thread.hpp"void Print() { std::cout << "Step in" << std::endl; while (true) { std::cout << "I am running" << std::endl; sleep(1); }}int cnt = 0;std::string GetName() { std::string name = "thread : " + std::to_string(cnt); cnt++; return name;}int main() { pthread_t tid = 0; MyThread th(tid, GetName(), Print); th.Start(); th.Join(); return 0;}
注意事项
- 静态成员函数:
ThreadRoutine
必须是静态的,因为它作为线程入口点,不能持有MyThread
实例。 - 参数传递:
Start
方法将this
作为参数传递给pthread_create
,允许线程实例在静态成员函数中访问自身的成员。 - 线程结束:使用
Join
方法等待线程结束,并正确释放资源。
线程互斥
多个线程同时访问公共资源(临界区域)可能导致竞态条件(Race Condition),导致数据一致性问题。解决方法是使用互斥锁(Mutex)。
模拟抢票问题
#include#include #include int ticket = 100;void *route(void *arg) { char *id = (char *)arg; while (1) { pthread_mutex_lock(nullptr); if (ticket > 0) { usleep(1000); printf("%s sells ticket %d\n", id, ticket); ticket--; } else { pthread_mutex_unlock(nullptr); break; } } return nullptr;}int main() { pthread_t t1, t2, t3, t4; pthread_create(&t1, nullptr, route, (void *)"thread 1"); pthread_create(&t2, nullptr, route, (void *)"thread 2"); pthread_create(&t3, nullptr, route, (void *)"thread 3"); pthread_create(&t4, nullptr, route, (void *)"thread 4"); pthread_join(t1, nullptr); pthread_join(t2, nullptr); pthread_join(t3, nullptr); pthread_join(t4, nullptr); return 0;}
解释
- 互斥锁:确保只有一个线程可以访问
ticket
,防止票被多次购买。 - 线程启动:使用
pthread_create
创建四个售票线程。 - 等待线程:使用
pthread_join
等待所有线程完成操作。
优化票卖逻辑
void *route(void *arg) { char *id = static_cast(arg); while (1) { pthread_mutex_lock(&mutex); if (ticket > 0) { sleep(1); // 模拟购票耗时 printf("%s sells ticket %d\n", id, ticket); ticket--; } pthread_mutex_unlock(&mutex); if (ticket <= 0) { break; } } return nullptr;}
###Linux下的互斥锁接口
在 Linux 中,互斥锁接口包括以下函数:
pthread_mutex_init(pthread_mutex_t mutex, const pthread_mutexattr_t *)
:初始化互斥锁。pthread_mutex_destroy(pthread_mutex_t mutex)
:销毁互斥锁。pthread_mutex_lock(pthread_mutex_t mutex)
:锁定互斥锁。pthread_mutex_trylock(pthread_mutex_t mutex)
:非阻塞锁定互斥锁。pthread_mutex_unlock(pthread_mutex_t mutex)
:解锁互斥锁。pthread_mutexattr_init(pthread_mutexattr_t *attr)
:初始化互斥锁属性。pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
:设置互斥锁属性类型。
结论
通过使用互斥锁,可以有效地保护共享资源,防止竞态条件。掌握这些知识对于开发安全的多线程程序至关重要,确保程序稳定运行。
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.116.15.85]2025年04月24日 08时58分14秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Kubernetes实战(三十三)-外部Etcd集群部署与调优(更安全的数据存储策略)
2025-04-03
Kubernetes快速上手:部署、使用及核心概念解析
2025-04-03
lamp 一键安装
2025-04-04
laravel 之 Eloquent 模型修改器和序列化
2025-04-04
Laravel项目宝塔部署全攻略:从0到1的实战指南
2025-04-04
laravl 文件存储云存储
2025-04-04
LaTeX伪代码编辑
2025-04-04
Latex相关文章
2025-04-04
leaflet删除所有图层(leaflet篇.25)
2025-04-04
leaflet加载接入天地图(leaflet篇.1)
2025-04-04
leaflet加载接入腾讯矢量、腾讯影像地图(leaflet篇.4)
2025-04-04
leaflet区域聚合点(点击后散开并进行合理定位)(leaflet篇.22)
2025-04-04
leaflet叠加geojson图层(leaflet篇.38)
2025-04-04
leaflet面采集与面编辑(leaflet篇.7)
2025-04-04
Leedcode3- Max Points on a Line 共线点个数
2025-04-04
LeetCode OJ:Merge k Sorted Lists(归并k个链表)
2025-04-05
leetcode Plus One
2025-04-05
LeetCode Text Justification
2025-04-05