学习C++多线程基础

C++多线程笔记

  • 最简单的创建线程(直接用一个函数为子线程入口)
//线程入口
void Mysthread()
{ 
	cout << "线程开始" << endl;
	cout << "线程结束" << endl;
}
int main()
{
    //创建线程,一创建就相当于开启线程
	thread my_thread(Mysthread);
	//等待子线程my_thread运行完再继续运行
	my_thread.join();
	//my_thread.detach();//这个是不等待子线程运行和join不能一起用,且必须有一个。
} 
  • 用一个类来作为线程入口
class My_obj
{
public:
	void operator()()   //重载()
	{
		cout << "线程开始" << endl;
		cout << "线程结束" << endl;
	}
};
int main()
{
	My_obj myobj;
	thread my_thread(myobj);  //会调用My_obj的拷贝函数,复制一份数据到子线程
	my_thread.join();
}
  • 带参数的子线程
void Mysthread(const int &i,char *ch,const string str)//用引用其实也是用了复制和主线程不是同一个数据(相当于值传递)
{                                    //指针就是用原来的数,真正的指针传递(用detach()的话就要注意)
	cout << "线程开始" << endl;
	cout << "线程结束" << endl;
}
int main()
{
	int m = 1;
	char mych[] = "this is a test!";
	thread my_thread (Mysthread,m,mych,(string)mych);//避免隐式引用,特别是detach()
	my_thread.join();
}
  • 互斥锁(mutex)(lock和unlock要成对使用)
    ——每个共享数据都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该数据。 (有多个锁的话,锁上的顺序要一样,要不然会造成死锁)
class A {
public:
	void inMsgRecvQueue()
	{
		for (int i = 0; i < 100000; i++)
		{			 
		   //操作共享数据要锁上
			my_mutex.lock();
			msgRecvQueue.push_back(i);
			//操作完要开锁
			my_mutex.unlock();
		}
	}
	void outMsgRecvQueue()
	{
		for (int i = 0; i < 100000; i++)
		{
		   //操作共享数据要锁上
			my_mutex.lock();
			if (!msgRecvQueue.empty())
			{
				int num = msgRecvQueue.front();
				msgRecvQueue.pop_front();
			}
			//操作完要开锁
			my_mutex.lock();
		}
	}
private:
    //共享数据
	list<int> msgRecvQueue;
    //互斥锁
	mutex my_mutex;
};

int main()
{
	A myobj;
	thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);
	thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
	myInMsgObj.join();
	myOutMsgObj.join();
}
  • “智能的互斥锁”
    ——其是个类,在构造这个类时,调用构造函数会把参数的mutex给lock上,然后其析构函数里面就会调用unlock。
  • std::lock_guard
std::lock_guard<std::mutex> my_guard(my_mutex);
std::lock_guard<std::mutex> my_guard(my_mutex,std::adopt_lock);//告诉其不用在构造函数中不用对my_mutex上锁
  • std::unique_lock

std::unique_lock<std::mutex> my_unique_lock(my_mutex);

//告诉其不用在构造函数中不用对my_mutex上锁
std::unique_lock<std::mutex> my_unique_lock(my_mutex,std::adopt_lock);

//获取不到锁,会继续向下运行。可以用my_unique_lock.owns_lock来查看是否获取到锁。
std::unique_lock<std::mutex> my_unique_lock(my_mutex,std::try_to_lock);

//把my_mutex与my_unique_lock关联,其实也就是把my_mutex封装一层。
//其成员函数有lock,unlock(如果lock状态下,调用析构函数时也会自己unlock),
//try_lock,release(取消关联,如果取消关联后就要自己去把锁unlock)
std::unique_lock<std::mutex> my_unique_lock(my_mutex,std::try_to_lock);


获取当前线程的id:
std::this_thread::get_id()

使得子线程参数真正做到传递地址:
std::ref()函数

使得线程休眠:
std::chrono::milliseconds dura(1000);//1000毫秒=1秒
std::this_thread::sleep_for(dura);

移动语义(对象转移,不进行复制)
std::move()


在学习C++多线程的时候的一些不懂的东西的大杂烩:
  • C++的会用到.和::和->的区别。
  1. A.B则A为对象或者结构体;
  2. A->B则A为指针,->是成员提取,A->B是提取A中的成员B,A只能是指向类、结构、联合的指针;
  3. A::B表示作用域A中的名称B,A可以是名字空间、类、结构;
  • Lambda表达式
    主要参考:https://www.cnblogs.com/DswCnblog/p/5629165.html
  1. []捕抓的变量在函数体里要改变要在后加上mutable 如:
int a = 111, b = 222;
        auto func = [=, &b]()mutable {
         a = 22; b = 333; cout << "a:" << a << " b:" << b <<endl;
          };//输出的是a:22 b:333

        func();
         cout << "a:" << a << " b:" << b << endl;//输出的是a:111 b:333
  1. []想使得捕抓的变量在外部也改变要用引用捕抓,若是传值相当于只是复制了一份数据进函数体内使用,如上的代码,a就是不会改变外部的值,而b会改变外部的值。
  • C++ const用法
    主要参考:https://www.cnblogs.com/Forever-Kenlen-Ja/p/3776991.html
  1. const,修饰变量时表示其为常数,有define的效果,且会比define好(方便效率高),完整理由可参考:https://blog.csdn.net/weibo1230123/article/details/81981384
  2. 将函数传入参数声明为const,以指明使用这种参数仅仅是为了效率的原因,而不是想让调用函数能够修改对象的值。
  • 要用引用的参数就要用const 。

  • sort包含在头文件algorithm中。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值