关于多线程,你需要了解的一些基础知识1---创建及其一般操作

225 阅读4分钟

一 启动线程的几种方法和线程标识符操作

  • 1.普通函数

  • 2.类对象(1类中重载小括号()运算符 2普通的成员函数)

  • 3.lambda


#include <iostream>
#include <thread>//我们通过thread来建立多线程

using namespace std;

void my_function() {
	cout<<"第一个线程标识符为:"<<std::this_thread::get_id()<<endl;
	cout << "我的第一个进程开始啦" << endl;
	cout << "我的第一个进程结束啦" << endl;
}

class MyClass {
public:
	void operator() () {
		cout << "第二个线程标识符为:" << std::this_thread::get_id() << endl;
		cout << "我的第二点一个进程开始啦" << endl;
		cout << "我的第二点一个进程结束啦" << endl;
	}
	void Myprint_class() {
		cout << "第三个线程标识符为:" << std::this_thread::get_id() << endl;
		cout << "我的第二点二个进程开始啦" << endl;
		cout << "我的第二点二个进程结束啦" << endl;
	}

};

int main()
{
	thread myprocess_1(my_function);
	//第一个线程标识符也可这样求出为:" << myprocess_1.get_id() << endl;
	
	myprocess_1.join();
	//std::thread::id master_thread;
	cout << "当前线程标识符为:" << std::this_thread::get_id() << endl;

	MyClass myclass;
	thread myprocess_2_1(myclass);
	cout <<"主线程一直为:"<< std::this_thread::get_id() << endl;
	myprocess_2_1.join();

	thread myprocess_2_2(&MyClass::Myprint_class, myclass);
	myprocess_2_2.join();

	auto my_lamda = [] {
		cout << "我的第三个进程开始啦" << endl;
		cout << "我的第三个进程结束啦" << endl;
	};
	thread myprocess_3(my_lamda);
	myprocess_3.join();

	cin.get();
}

二 向线程函数传递参数

  • 1.向线程函数传递参数比较简单,一般的形式如下
void f(int i,std::string const& s);
std::thread t(f,3, "hello");
  • 2.但仍然有一些特殊情况,有时换我们想传递一些引用, 但是发现我们传递的对象是对象的拷贝而不是对象本身,如下所示:

void update_data_for_widget(widget_id    w,widget_data&    data);    //    1
void oops_again(widget_id    w)
{
    widget_data    data;
    std::thread    t(update_data_for_widget,w,data);    //    2
    display_status();
    t.join();
    process_widget_data(data);    //    3
}
  • 3.这里就要注意2启动的新进程中传递的参数并不是参数本身,而是参数的拷贝 如果我们向传递参数本身的话,要这么写:

std::thread t(update_data_for_widget,w,std::ref(data))
class X
{
public:
    void do_lengthy_work();
};
X my_x;
std::thread t(&X::do_lengthy_work,&my_x);    //    1
  • 4.在这段代码中,将my_x.do_lengthy_work作为线程函数, my_x的地址1作为指针对象提供给函数,如果函数有参数的话可以为成员函数提供参数:
    std::thread构造函数的第三个参数就是成员函数的第一个参数,以此类推。
class X
{
public:
    void do_lengthy_work(int num);
};
X my_x;
std::thread t(&X::do_lengthy_work,&my_x,num); 

三 转移线程所有权及相关操作

  • 1.函数返回值为线程
 std::thread f()
{
	void some_function();
	return std::thread(some_function);
}
std::thread g()
{
	void some_other_function(int);
	std::thread t(some_other_function,42);
	return t;
}
  • 2.scoped thread的实例用法
class scoped_thread
{
	std::thread t;
public:
	explicit scoped_thread(std::thread t_):			//1
		t(std::move(t_))			
	{
			if(!t.joinable())						//2
				throw std::logic_error("No thread");
	}
	
	~scoped_thread()
	{
		t.join();								//3
	}
				
	scoped_thread(const scoped_thread&) = delete;
	scoped_thread& operator=(const scoped_thread&) = delete;
};
 
struct func;
 
void f()
{
	int some_local_state;
	scoped_thread t(std::thread(func(some_local_state)));		//4
	do_something_in_current_thread();
}
  • 3.用于容器的量产一些线程,并且等待它们结束:
void do_work(unsigned id);
void f()
{
	std::vector<std::thread> threads;
	for(unsigned i=0;i<20;++i)
	{
		threads.push_back(std::thread(do_work,i));
	}
	//在每一个线程上调用join
	std::for_each(threads.begin(),threads.end(),std::mem_fn(&std::thread::join);
}

四.thread_group和mutex(互斥锁)的使用

1:thread_group是线程组的意思,可以实现对多个线程统一管理

2:成员函数如下

3: 多个线程访问同一资源时,为了保证数据的一致性,最简单的方式就是使用 mutex(互斥锁)

#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>

using namespace boost;
using namespace std;

mutex iomutex;

void runChild(const int n)
{
    {
        mutex::scoped_lock lock(iomutex);
        cout << "我是第" << n << "个子线程" << endl;
    }

    {
        mutex::scoped_lock lock(iomutex);
        cout << "进程" << n << "退出" << endl;
     }
}

int main(int argc, char** argv)
{
   thread_group group;
   for(int num=0;num<10;num++)
       group.create_thread(bind(&runChild,num));
   group.join_all();
}

五.unique_lock

#include <iostream>
#include <thread>
#include <mutex>
#include <deque>

class A
{
public:
	void WriteFunction()
	{
		for (int i = 0; i < 1000; ++i)
		{
			std::unique_lock<std::mutex> my_uniquelock_1(my_mutex_1);
			
			std::cout << "向队列中添加一个元素" << std::endl;
			my_deque.push_back(i);
		}
	}
	void ReadFunction()
	{
		for (int i = 0; i < 1000; ++i)
		{
			std::unique_lock<std::mutex> my_uniquelock_1(my_mutex_1);
			if (!my_deque.empty())
			{
				std::cout << "读出队列的第一个元素: " << my_deque.front() << std::endl;
				my_deque.pop_front();
			}
			
		}
	}
private:
	std::deque<int> my_deque;
	std::mutex my_mutex_1;
 
};
int main()
{
	A a;
	std::thread my_thread_1(&A::WriteFunction, std::ref(a));
 
	std::thread my_thread_2(&A::ReadFunction, std::ref(a));
 
	my_thread_1.join();
	my_thread_2.join();
    std::cout << "Hello World!\n";
}