多线程学习记录2
来源:互联网 发布:ubuntu输入法设置中文 编辑:程序博客网 时间:2024/06/05 06:20
使用多个锁导致的死锁问题
code 7:
#include <iostream>#include <thread>#include <mutex>#include <string>#include <fstream>//std::mutex mu;class LogFile{public:LogFile(){//f.open("log.txt");}void log1(std::string s, int i){std::lock_guard<std::mutex> lg1(m_mutex1);std::lock_guard<std::mutex> lg2(m_mutex2);std::cout<< " count i:" << i << std::endl;}void log2(std::string s, int i){std::lock_guard<std::mutex> lg2(m_mutex2);std::lock_guard<std::mutex> lg1(m_mutex1);std::cout << " count i:" << i << std::endl;}protected:private:std::mutex m_mutex1;std::mutex m_mutex2;};void test_funtion(LogFile& lf){for (int i = 0; i < 100; ++i){lf.log1("test_funtion ", i);}}int main(){LogFile logFile;std::thread t1(test_funtion,std::ref(logFile));for (int i = 0; i < 100; ++i){logFile.log2("main ", i);}t1.join();return 0;}代码中log1和log2没有实际功能,只是为了测试,当需要多个锁时,若上锁的顺序不同,可能会发生死锁现象。t1线程执行到log1,锁住m_mutex1,马上要执行
std::lock_guard<std::mutex> lg2(m_mutex2);主线程执行到log2,锁住m_mutex2,马上要执行
std::lock_guard<std::mutex> lg1(m_mutex,1);
这样t1会等待m_mutex2释放,而主线程会等待m_mutex1释放,这样就死锁了。所以要保证mutex上锁的顺序要一致,使用这种办法可以不用操心上锁顺序
void log1(std::string s, int i){std::lock(m_mutex1, m_mutex2);std::lock_guard<std::mutex> lg1(m_mutex1,std::adopt_lock);std::lock_guard<std::mutex> lg2(m_mutex2, std::adopt_lock);std::cout<< " count i:" << i << std::endl;}void log2(std::string s, int i){std::lock(m_mutex1, m_mutex2);std::lock_guard<std::mutex> lg2(m_mutex2, std::adopt_lock);std::lock_guard<std::mutex> lg1(m_mutex1, std::adopt_lock);std::cout << " count i:" << i << std::endl;}
code8:
#include <iostream>#include <thread>#include <mutex>#include <string>#include <fstream>class LogFile{public:LogFile(){//f.open("log.txt");}void log1(std::string s, int i){std::lock_guard<std::mutex> lg1(m_mutex1);std::cout<< " count i:" << i << std::endl;}protected:private:std::mutex m_mutex1;//std::fstream f;};void test_funtion(LogFile& lf){for (int i = 0; i < 100; ++i){lf.log1("test_funtion ", i);}}int main(){LogFile logFile;std::thread t1(test_funtion,std::ref(logFile));for (int i = 0; i < 100; ++i){logFile.log1("main ", i);}t1.join();return 0;}可以使用unique_lock代替lock_guard,unique_lock使用更为灵活。
void log1(std::string s, int i){std::unique_lock<std::mutex> lg1(m_mutex1);std::cout<< " count i:" << i << std::endl;lg1.unlock();//可灵活上锁解锁lg1.lock();lg1.unlock();}
void log1(std::string s, int i){std::unique_lock<std::mutex> lg1(m_mutex1,std::defer_lock);//未上锁lg1.lock();std::cout<< " count i:" << i << std::endl;lg1.unlock();lg1.lock();lg1.unlock();}code9:
#include <iostream>#include <thread>#include <mutex>#include <string>#include <fstream>std::mutex mu;class LogFile{public:LogFile(){f.open("log.txt");}void log(std::string s, int i){std::lock_guard<std::mutex> lg(m_mutex);f << s << " count i:" << i << std::endl;}protected:private:std::mutex m_mutex;//保护fstd::ofstream f;};void test_funtion(LogFile& lf){for (int i = 0; i < 100; ++i){lf.log("test_funtion ", i);}}int main(){LogFile logFile;std::thread t1(test_funtion, std::ref(logFile));for (int i = 0; i < 100; ++i){logFile.log("main ", i);}t1.join();return 0;}LogFile在构造函数打开txt文件,这个没有必要,什么时候用什么时候打开就好。可以改成:
class LogFile{public:LogFile(){}void log(std::string s, int i){if (!f.is_open()){std::lock_guard<std::mutex> lg(m_mutex_open);f.open("log.txt");}std::lock_guard<std::mutex> lg(m_mutex);f << s << " count i:" << i << std::endl;}protected:private:std::mutex m_mutex;//打印使用std::mutex m_mutex_open;//打开文件使用std::ofstream f;};这样也不是线程安全的,如果多个线程都执行至
std::lock_guard<std::mutex> lg(m_mutex_open);一个线程释放m_mutex_open后,另一个线程会再次打开f,会导致f被打开两次。所以is_open应该和open同步,这样
void log(std::string s, int i){{if (!f.is_open()){std::lock_guard<std::mutex> lg(m_mutex_open);f.open("log.txt");}}std::lock_guard<std::mutex> lg(m_mutex);f << s << " count i:" << i << std::endl;}频繁上锁解锁会影响性能,c++11提供了更好的办法Lazy Initialization
class LogFile{public:LogFile(){}void log(std::string s, int i){std::call_once(m_flag_open, [&](){f.open("log.txt"); });std::lock_guard<std::mutex> lg(m_mutex);f << s << " count i:" << i << std::endl;}protected:private:std::mutex m_mutex;//打印使用std::once_flag m_flag_open;//std::mutex m_mutex_open;//打开文件使用std::ofstream f;};
阅读全文
0 0
- 多线程学习记录2
- 多线程学习记录2--代码
- iphone多线程-学习记录
- java多线程学习记录
- 多线程学习记录3
- java多线程学习记录
- python 多线程学习记录
- Java多线程学习记录
- 多线程学习记录1
- JAVA学习记录—多线程
- 记录多线程学习之路
- java多线程学习疑惑记录
- 多线程学习记录2-java5的一些线程池
- 记录多线程成长----2
- 黑马程序员_学习记录11:多线程
- 多线程学习记录3-读写锁
- 多线程学习记录4-Lock锁
- 多线程学习过程记录(python)
- for each
- 《HTML之表单》
- 运算符之:3、关系运算符(6个)
- 笔试整理 六
- springmvc+mybatis配置过程及示例
- 多线程学习记录2
- 234-Palindrome Linked List
- 决策树:ID3算法
- Struts2基础01:编写第一个HelloStruts2程序
- SpringMVC(二)
- 线程池是什么?线程池的作用?
- 运算符之:4、逻辑运算符(6个)
- crontab 无法重启tomcat的问题
- day01_前言知识