您的位置:首页 > 编程语言 > C语言/C++

C++工程师面试宝典系列之多线程编程

2017-02-12 21:33 337 查看
3.数据竞争与互斥对象

#include <iostream>
#include <thread>
#include <string>
using namespace std;

void function_1() {
for (int i = 0; i > -100;i--)
cout << "From t1:" <<i<< endl;

}

//主线程和t1线程竞争来执行cout

int main() {
thread t1(function_1);
for (int i = 0; i < 100; i++)
cout << "From main:" << i << endl;

t1.join();

return 0;
}

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
using namespace std;

mutex mu;

void shared_print(string msg, int id)
{
mu.lock();
cout << msg << id << endl;     //互斥对象,可能会发生异常
mu.unlock();
}

void function_1() {
for (int i = 0; i > -100;i--)
shared_print("From t1:",i);

}

int main() {
thread t1(function_1);
for (int i = 0; i < 100; i++)
shared_print("From main::", i);

t1.join();

return 0;
}

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
using namespace std;

mutex mu;

void shared_print(string msg, int id)
{
lock_guard<mutex> guard(mu);
//mu.lock();
cout << msg << id << endl;     //互斥对象,可能会发生异常
//mu.unlock();
}

void function_1() {
for (int i = 0; i > -100;i--)
shared_print("From t1:",i);

}

int main() {
thread t1(function_1);
for (int i = 0; i < 100; i++)
shared_print("From main::", i);

t1.join();

return 0;
}

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <fstream>
using namespace std;

class LofFile
{
public:
LofFile(){
f.open("log.txt");
}
void shared_print(string id, int value)
{
lock_guard<mutex> locker(m_mutex);
f << "From" << id << ":" << value << endl;
}
//ofstrteam& GetStream(){return f;}
/*
void processf(void fun(ofstream&))
{
fun(f);
}
*/
protected:

private:
mutex m_mutex;
ofstream f;
};

void function_1(LofFile& log) {
for (int i = 0; i > -100;i--)
log.shared_print("From t1:",i);

}

int main() {
LofFile log;
thread t1(function_1,ref(log));
for (int i = 0; i < 100; i++)
log.shared_print("From main::", i);

t1.join();

return 0;
}


=======================================================================================

4.死锁

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <fstream>
using namespace std;

class LofFile
{
mutex m_mutex;
ofstream f;  //被m_mutex保护的对象
public:
LofFile(){
f.open("log.txt");  //构造函数打开log.txt文件
}
void shared_print(string id, int value)
{
lock_guard<mutex> locker(m_mutex);
cout<< "From" << id << ":" << value << endl;
}
};

void function_1(LofFile& log) {
for (int i = 0; i > -100;i--)
log.shared_print("From t1:",i);

}

int main() {
LofFile log;
thread t1(function_1,ref(log));
for (int i = 0; i < 100; i++)
log.shared_print("From main::", i);

t1.join();

return 0;
}


#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <fstream>
using namespace std;

class LofFile
{
mutex m_mutex;
mutex m_mutex2;
ofstream f;  //被m_mutex保护的对象
public:
LofFile(){
f.open("log.txt");  //构造函数打开log.txt文件
}
void shared_print(string id, int value)
{
lock_guard<mutex> locker(m_mutex);
lock_guard<mutex> locker2(m_mutex2);
cout<< "From" << id << ":" << value << endl;
}
void shared_print2(string id, int value)
{
lock_guard<mutex> locker2(m_mutex2);
lock_guard<mutex> locker(m_mutex);
cout << "From" << id << ":" << value << endl;
}
};

void function_1(LofFile& log) {
for (int i = 0; i > -100;i--)
log.shared_print("From t1:",i);

}

int main() {
LofFile log;
thread t1(function_1,ref(log));
for (int i = 0; i < 100; i++)
log.shared_print2("From main::", i);

t1.join();

return 0;
}

void shared_print(string id, int value)
{
lock_guard<mutex> locker(m_mutex);
lock_guard<mutex> locker2(m_mutex2);
cout<< "From" << id << ":" << value << endl;
}
void shared_print2(string id, int value)
{
lock_guard<mutex> locker2(m_mutex);
lock_guard<mutex> locker(m_mutex2);
cout << "From" << id << ":" << value << endl;
}

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <fstream>
using namespace std;

class LofFile
{
mutex m_mutex;
mutex m_mutex2;
ofstream f;  //被m_mutex保护的对象
public:
LofFile(){
f.open("log.txt");  //构造函数打开log.txt文件
}
void shared_print(string id, int value)
{
lock(m_mutex, m_mutex2);
lock_guard<mutex> locker(m_mutex,adopt_lock);
lock_guard<mutex> locker2(m_mutex2,adopt_lock);
cout<< "From" << id << ":" << value << endl;
}
void shared_print2(string id, int value)
{
lock(m_mutex, m_mutex2);
lock_guard<mutex>
ce5d
locker2(m_mutex2,adopt_lock);
lock_guard<mutex> locker(m_mutex,adopt_lock);
cout << "From" << id << ":" << value << endl;
}
};

void function_1(LofFile& log) {
for (int i = 0; i > -100;i--)
log.shared_print("From t1:",i);

}

int main() {
LofFile log;
thread t1(function_1,ref(log));
for (int i = 0; i < 100; i++)
log.shared_print2("From main::", i);

t1.join();

return 0;
}
避免死锁的总结:
(1)首先需要评估程序是否需要2个以上的mutex,如果一个就可以满足要求,则不存在死锁的问题;

(2)避免在使用mutex的同时去调用不熟悉的函数,可能这个函数包含了另外的锁;

(3)如果需要同时使用两个mutex,则可以使用c++标准库提供的lock函数,确保mutex的顺序是相同的;

=======================================================================================

4.Unique Lock 和 Lazy Initialization

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <fstream>
using namespace std;

class LofFile
{
mutex m_mutex;
ofstream f;  //被m_mutex保护的对象
public:
LofFile(){
f.open("log.txt");  //构造函数打开log.txt文件
}
void shared_print(string id, int value)
{
//lock_guard<mutex> locker(m_mutex);
unique_lock<mutex> locker(m_mutex,defer_lock);
//...
locker.lock();
f<< "From" << id << ":" << value << endl;
locker.unlock();
//...

locker.lock();

unique_lock<mutex> locker2 = move(locker);
}
};

void function_1(LofFile& log) {
for (int i = 0; i > -100;i--)
log.shared_print(string("From t1:"),i);

}

int main() {
LofFile log;
thread t1(function_1,ref(log));
for (int i = 0; i < 100; i++)
log.shared_print("From main::", i);

t1.join();

return 0;
}

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <fstream>
using namespace std;

class LofFile
{
mutex m_mutex;
//mutex m_mutex_open;
once_flag m_flag;
ofstream f;  //被m_mutex保护的对象
public:
LofFile(){
//f.open("log.txt");  //构造函数打开log.txt文件
}
void shared_print(string id, int value)
{
/*{
unique_lock<mutex> locker(m_mutex_open, defer_lock);
if (!f.is_open())
{
f.open("log.txt");
}
}*/
call_once(m_flag, [&](){f.open("log.txt"); });
unique_lock<mutex> locker(m_mutex,defer_lock);
f<< "From" << id << ":" << value << endl;
}
};

void function_1(LofFile& log) {
for (int i = 0; i > -100;i--)
log.shared_print(string("From t1:"),i);

}

int main() {
LofFile log;
thread t1(function_1,ref(log));
for (int i = 0; i < 100; i++)
log.shared_print("From main::", i);

t1.join();

return 0;
}


=======================================================================================

5.条件变量

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <fstream>
#include <deque>
#include <functional>
#include <condition_variable>

using namespace std;

deque<int> q;    //声明一个全局变量,类型是一个整型的队列
mutex mu;      //声明一个互斥对象mu
condition_variable cond;  //条件变量

void function_1() {
int count = 10;
while (count = 10){
unique_lock<mutex> locker(mu);
q.push_front(count);  //每一次循环都会将一个数字push到队列q中
locker.unlock();
//cond.notify_one();//会激活整个条件的线程
cond.notify_all();//线程1传入数据后通知线程2运行
this_thread::sleep_for(chrono::seconds(1));//线程sleep一秒钟
count--;
}
}
void function_2(){
int data = 0;
while (data != 1){
unique_lock<mutex> locker(mu);
cond.wait(locker, [](){return !q.empty(); });//重复的加解锁,只能使用unique_lock,不能使用lock_guard
//if (!q.empty()){  //如果队列不空,队列会pop出一个数
data = q.back();
q.pop_back();
locker.unlock();
cout << "t2 get a value from t1:" << data << endl;
}
/*
else{
locker.unlock(); //如果队列为空,则解锁,进入下一个循环
//this_thread::sleep_for(chrono::milliseconds(10));
//如果队列为空,等待10秒后进入下一个循环
}
*/
}

//function_1是数据的生成者,function_2是数据的消费者

int main(){
thread t1(function_1);
thread t2(function_2);
t1.join();
t2.join();
return 0;
}


=======================================================================================

6.Future , Promise 和 async()

(1)future类是一个可以从未来获取某个变量的类,future的get函数只能被调用一次;

(2)async()不一定会创建子线程,取决于async()的第一个参数;

async(lauch::deferred,factorial.4);//延迟启动
async(launch::async,factorial,4);//创建另一个子线程来启动factorial

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <fstream>
#include <future>

using namespace std;
/*
//全局变量
mutex mu;//需要lock和unlock函数
condition_variable cond;//需要notify和wait函数
*/
//int factorial(int N,int & x ){//添加一个参数,创建引用x
int factorial(int N){
int res = 1;
for (int i = N; i > 1; i--)
res *= i;

cout << "result is :" <<res<< endl;

return res;
}

int main(){
int x;
//thread t1(factorial,4,ref(x));//创建一个变量x,传递给线程1
future<int> fu = async(factorial,4);
x = fu.get();
//t1.join();
return 0;
}

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <fstream>
#include <future>

using namespace std;

int factorial(future<int>& f){
int res = 1;

int N = f.get();
for (int i = N; i > 1; i--)
res *= i;

cout << "result is :" <<res<< endl;

return res;
}

int main(){
int x;

promise<int> p;
future<int> f = p.get_future();
p.get_future();
//thread t1(factorial,4,ref(x));//创建一个变量x,传递给线程1
future<int> fu = async(launch::async,factorial,ref(f));

p.set_value(4);
x = fu.get();
cout << "Get form child" << x << endl;
//t1.join();
return 0;
}

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <fstream>
#include <future>

using namespace std;

int factorial(shared_future<int> f){
int res = 1;

int N = f.get();//抛出异常 std::future_errc::broken_promise
for (int i = N; i > 1; i--)
res *= i;

cout << "result is :" <<res<< endl;

return res;
}

int main(){
int x;

promise<int> p;
//promise<int> p2 = move(p);
future<int> f = p.get_future();
//p.get_future();
//thread t1(factorial,4,ref(x));//创建一个变量x,传递给线程1

shared_future<int> sf = f.share();
future<int> fu = async(launch::async,factorial,sf);
future<int> fu2 = async(launch::async, factorial, sf);
future<int> fu3 = async(launch::async, factorial, sf);
future<int> fu4 = async(launch::async, factorial, sf);
//...10线程
p.set_value(4);
//x = fu.get();
//cout << "Get form child" << x << endl;
//t1.join();
return 0;
}


=======================================================================================

7.使用可调用对象

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <fstream>
#include <future>

using namespace std;

class A
{
public:
void f(int x, char c){}
int operator()(int N){ return 0; } //函数重载了
};

void foo(int x){}

int  main(){
A a;
//两种方法创建子线程,使用thread或者async函数
thread t1(a,6);//传递a的拷贝给子线程
thread t2(ref(a), 6);//传递a的引用给子线程
thread t3(move(a), 6);//将a从主线程移动到子线程中,a在主线程中不再有效
thread t4(A(),6);//传递临时创建的a对象给子线程

thread t5(foo, 6);//全局函数来创建子线程
thread t6([](int x){return x*x; },6);

thread t7(&A::f,a,8,'w');//传递a的拷贝的成员函数给子线程
thread t8(&A::f, &a, 8, 'w');//传递a的地址的成员函数给子线程

async(launch::async,a,6);

return 0;
}
=======================================================================================

8.packaged_task

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <fstream>
#include <future>
#include <deque>

using namespace std;

int factorial(int N){
int res = 1;

for (int i = N; i > 1; i--)
res *= 1;
cout << "Result is:" << res << endl;

return res;
}

std::deque<packaged_task<int()>> task_q;
std::mutex mu;
std::condition_variable cond;

void thread_1()
{
packaged_task<int()> t;
{
std::unique_lock<mutex> locker(mu);
cond.wait(locker, []{return !task_q.empty();});
t = std::move(task_q.front());
}
t();
}

int main(){
std::thread t1(thread_1);
std::packaged_task<int()> t(bind(factorial, 6));
std::future<int> ret = t.get_future();//获得与packaged_task共享状态相关联的future对象。

{
std::lock_guard<std::mutex> locker(mu);
task_q.push_back(std::move(t));
}

cond.notify_one();

int value = ret.get();//等待任务完成并获取结果。

t1.join();

/*
thread t1(factorial,6);
packaged_task<int()> t(bind(factorial,6));
future<int> ret = t.get_future();//获得与packaged_task共享状态相关联的future对象。
int value = ret.get();//等待任务完成并获取结果。
*/

/*
auto t = bind(factorial, 6);
t();
*/
return 0;
}


=======================================================================================

9.回顾和时间约束

#include <mutex>
#include <fstream>
#include <future>
#include <deque>

using namespace std;

int factorial(int N){
int res = 1;

for (int i = N; i > 1; i--)
res *= 1;
cout << "Result is:" << res << endl;

return res;
}

std::deque<packaged_task<int()>> task_q;
std::mutex mu;
std::condition_variable cond;

int main(){
std::thread t1(factorial,6);
std::this_thread::sleep_for(chrono::milliseconds(3));

chrono::steady_clock::time_point tp = chrono::steady_clock::now() + chrono::milliseconds(4);
std::this_thread::sleep_until(tp);

std::mutex mu;
std::unique_lock<std::mutex> locker(mu);
locker.try_lock_for(chrono::milliseconds(3));
locker.try_lock_until(tp);

std::condition_variable cond;
cond.wait_for(locker, chrono::milliseconds(3));
cond.wait_until(locker,tp);

std::promise<int> p;
std::future<int> f = p.get_future();
f.wait_for(chrono::milliseconds(3));
f.wait_until(tp);

return 0;
}
=======================================================================================
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: