(十一)boost库之多线程间通信
来源:互联网 发布:菲尼克斯之光 知乎 编辑:程序博客网 时间:2024/06/06 12:43
1、互斥锁
在编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。
#include <iostream>#include <boost/thread.hpp>using namespace std;int g_num = 0;
boost::mutex mu; //定义互斥锁对象
int Func(int nCount){for (int i = 0; i < nCount; i++){boost::mutex::scoped_lock lock(mu); //对共享数据进行操作,需加锁
g_num++;cout << __FUNCTION__ << ": " << g_num << endl;
}return g_num;
}int _tmain(int argc, _TCHAR* argv[]){boost::thread th1(Func, 100);boost::thread th2(Func, 200);th1.join();th2.join();return 0;
}
2、读写锁
boost::shared_mutex rw_mu; //定义读写锁
int Write(int nCount){for (int i = 0; i < nCount; i++){boost::unique_lock<boost::shared_mutex> lock(rw_mu); //加唯一锁
g_num++;cout << __FUNCTION__ << ": " << g_num << endl;
}return g_num;
}void Read(int nCount){for (int i = 0; i < nCount; i++){boost::shared_lock<boost::shared_mutex> lock(rw_mu); //加共享锁
cout << __FUNCTION__ << ": " << g_num << endl;
}}int _tmain(int argc, _TCHAR* argv[]){boost::thread th1(Write, 100);boost::thread th2(Read, 100);boost::thread th3(Read, 100);th1.join();th2.join();th3.join();return 0;
}
3、条件量
条件量相对于互斥锁和读写锁来说,并不是那么好理解,简单点说,条件变量就是用于等待某个条件被触发,但为什么要配合锁使用呢,因为我们的等待不能是干等,那样可能会出现死锁。
如线程A负责添加任务到队列,线程B负责处理队列中的任务,队列就是两个线程的共享资源,使用前必须加锁,但如果B线程加锁后,发现队列中没有数据,然后等待,A线程准备添加任务时,发现
锁已经被占用,于是就没法添加任务,就形成了死锁。但如果我等待时,释放锁资源,A线程就能正常添加任务,完成后通知B线程可以处理了,那么整个流程就畅通无阻了,这就是条件量的作用。
#include <queue>boost::mutex g_ioMutex; //输出控制锁
template<typename T>class CMsgQueue
{public:
CMsgQueue(size_t n):m_nCapacity(n){}void Push(const T& val){{boost::mutex::scoped_lock lock(m_mu); //加锁
while(m_val.size() == m_nCapacity) //队列已满{{boost::mutex::scoped_lock lock(g_ioMutex);cout << "队列已满" << endl;
}m_condPush.wait(m_mu); //等待,将暂时的解锁
}m_val.push(val); //添加数据到队列
}m_condPop.notify_one(); //通知读线程
}void Pop(T& val)
{{boost::mutex::scoped_lock lock(m_mu); //加锁
while(m_val.size() == 0) //队列为空{{boost::mutex::scoped_lock lock(g_ioMutex);cout << "队列为空" << endl;
}m_condPop.wait(m_mu); //等待可读,
}val = m_val.front(); //读取数据
m_val.pop();}m_condPush.notify_one(); //通知写线程
}private:
queue<T> m_val; //队列
int m_nCapacity; //队列最大容量boost::condition_variable_any m_condPush; //写入条件量
boost::condition_variable_any m_condPop; //读取条件量
boost::mutex m_mu; //互斥锁
};CMsgQueue<int> g_numQueue(10);
void FuncA(int nCount){for (int i = 0; i < nCount; i++){{boost::mutex::scoped_lock lock(g_ioMutex);cout << __FUNCTION__ << " Put " << i << endl;
}g_numQueue.Push(i);}}void FuncB(int nCount){for (int i = 0; i < nCount; i++){int val;
g_numQueue.Pop(val);boost::mutex::scoped_lock lock(g_ioMutex);cout << __FUNCTION__ << " Get " << val << endl;
}}int _tmain(int argc, _TCHAR* argv[]){boost::thread th1(FuncA, 50);boost::thread th2(FuncB, 20);boost::thread th3(FuncB, 30);th1.join();th2.join();th3.join();return 0;
}
在多线程程序中,锁的使用需要特别的小心,比如,我们将FuncA稍微改一下:
void FuncA(int nCount){for (int i = 0; i < nCount; i++){boost::mutex::scoped_lock lock(g_ioMutex);cout << __FUNCTION__ << " Put " << i << endl;
g_numQueue.Push(i);}}
如果改成这样,程序将陷入死锁,我们轻轻松松就制造了一个死锁案例。
A线程占用了输入锁,那么B线程的Pop函数将一直在获取输入锁的地方等待,但它已经占用了m_mu锁,A线程也就只能一直在等待m_mu,故形成了死锁。
0 0
- (十一)boost库之多线程间通信
- (十)boost库之多线程
- (十二)boost库之多线程高级特性
- iOS开发之多线程(线程间的通信)
- Boost之多线程
- Boost之多线程
- 【JAVA之多线程】6.线程间通信
- (6)Java之多线程通信
- (十一)、Java复习笔记之多线程(2)
- C#学习之多线程开发技术(十一)
- 黑马程序员--JAVA基础复习之多线程(三)线程间通信 生产者消费者
- boost线程间通信和传递参数
- Android学习笔记之多线程间的异步通信
- Android中的Http通信(四)之多线程下载数据
- boost线程库学习--(4)两个线程间使用队列进行通信
- 黑马程序员——java基础拾遗之多线程(二) 线程同步、线程通信
- 【Java并发编程】之十一:线程间通信中notify通知的遗漏(含代码)
- 【Java并发编程】之十一:线程间通信中notify通知的遗漏(含代码)
- 学习笔记:Spring Bean的作用域
- iOS添加字体汇总
- Java Web开发5___jQuery 中 按钮点击事件的几种写法
- 2016.03.14
- Delphi数据类型
- (十一)boost库之多线程间通信
- 156.Evaluate the following SQL statement:
- 常用文件存储方法参考
- 2705: [SDOI2012]Longge的问题|欧拉函数
- 跟我一起学Microsoft SQL Server 2012 Internals(2.1)
- Valgrind使用说明
- ADT的配置
- Android开发笔记(八十)运行状态检查
- css设置当前鼠标样式