C++11 多线程的实现
·
一、线程相关操作
1、线程的创建
线程体函数种类:
1、可以是任意类型的函数,不必要是 void * 类型参数也是void *类型
2、可以是全局函数,也可以是类中成员函数当做线程体
3、可以是仿函数当作线程体函数
4、也可以是Lambda表达式当作线程体函数
#include<myhead.h>
#include <thread> //要包含线程头文件
void func1(){
//输出当前线程的线程号
cout<<"func1的调用,id="<<this_thread::get_id()<<endl;
}
void func2(int num,string s){
cout<<"func2的调用"<<endl;
cout<<"num="<<num<<" s="<<s<<endl;
}
class ThreadTest{
private:
int num;
string name;
public:
void setNum(int num){
this->num=num;
}
void setName(string name){
this->name=name;
}
void func(){ //类中成员函数作为线程体函数
cout<<"thread 3 的调用"<<endl;
cout<<"num="<<num<<" name="<<name<<endl;
}
};
int main(int argc, const char *argv[]){
//1、创建第1个线程并执行线程体,线程体是无参函数
thread t1(func1);
//2、创建第2个线程并执行线程体,线程体是有参函数
thread t2(func2,1314,"name");
//3、创建第3个线程并执行线程体,线程体是类中成员函数
ThreadTest test;
test.setNum(520);
test.setName("zhangsan");
thread t3(&ThreadTest::func,&test);
//4、创建第4个线程并执行线程体,线程体是lambda表达式
int key=1024;
thread t4([](int key){
cout<<"thread 4 的调用"<<endl;
cout<<"key="<<key<<endl;
},key);
//阻塞回收分支线程
t1.join();
t2.join();
t3.join();
t4.join();
cout<<"hello thread"<<endl;
return 0;
}
运行结果:
注意:各个线程运行的先后顺序随机,此处仅展示其中一种运行结果

2、线程号的获取
该函数会返回一个很大的整数
this_thread::get_id()
3、线程的回收
1、阻塞方式回收线程:th1.join();
2、非阻塞形式回收线程:th.detach();
#include<myhead.h>
void func(){
for(int i=0;i<10;i++){
cout<<"hello thread"<<endl;
this_thread::sleep_for(std::chrono::seconds(1)); //等待1s的时间
}
}
int main(int argc, const char *argv[]){
thread t1(func);
// 阻塞回收分支线程
//th1.join();
t1.detach(); //将线程设置成分离态,主线程可以干自己其他事情
cout<<"exit"<<endl;
this_thread::sleep_for(std::chrono::seconds(5)); //等待1s的时间
return 0;
}
二、互斥锁
互斥锁本质上是完成将多个线程使用临界资源时,防止竞态。
常用函数:
1、构造函数:创建一个互斥锁对象
2、lock():上锁
3、unlock()释放锁资源
#include<myhead.h>
#include<mutex> //引入互斥锁头文件
mutex mux;
void task(){
mux.lock();
cout<<"---------------"<<endl;
cout<<"tid = "<<this_thread::get_id()<<endl;
cout<<"***************"<<endl;
mux.unlock();
}
int main(int argc, const char *argv[]){
for(int i=0;i<10;i++){
thread t(task);
t.detach();
}
this_thread::sleep_for(std::chrono::seconds(5));
return 0;
}
三、条件变量
实现一个生产者对应多个消费者问题
常用函数
1、构造函数:创建并初始化一个条件变量
2、wait():将消费者线程放入等待队列中
3、唤醒线程:
cond.notify_one(); 唤醒一个线程
cond.notify_all(); 唤醒所有线程
#include<myhead.h>
#include<mutex>
#include<condition_variable> //引入条件变量头文件
condition_variable cond;
mutex mux;
void producerProcess(){ //生产者
while(1){
this_thread::sleep_for(std::chrono::seconds(1));
cout<<"生产了一件物品"<<endl;
//通知一个线程可以消费了
cond.notify_one();
//通知所有消费者线程
//cv.notify_all();
}
}
void consumerProcess(){ //消费者
while(1){
unique_lock<mutex> lock(mux); //自动上锁
cond.wait(lock);
cout<<"消费了一件物品"<<endl;
lock.unlock(); //解锁
}
}
int main(int argc, const char *argv[]){
thread p1(producerProcess);
thread c1(consumerProcess);
thread c2(consumerProcess);
p1.join();
c1.join();
c2.join();
return 0;
}
四、实例
1、多线程实现linux的 cp 指令,一个线程拷贝文件前一半,另一个拷贝后一半。
#include <myhead.h>
/*
src:源文件描述符
dest:拷贝后的文件描述符
start:拷贝开始的起点
size:本次拷贝的字节数
*/
void task(int src,int dest,int start,int size){
lseek(src,start,SEEK_SET);
lseek(dest,start,SEEK_SET);
int sum=0;
char buf[128];
while(1){
int pos=read(src,buf,sizeof(buf));
sum+=pos;
if(sum>=size){
write(dest,buf,pos-(sum-size));
break;
}
write(dest,buf,pos);
}
}
int main(int argc, const char *argv[]){
if(argc!=3){
printf("copy error\n");
printf("usage: ./copy srcfile destfile\n");
return -1;
}
int srcfd=-1,destfd=-1;
if((srcfd=open(argv[1],O_RDONLY))==-1){
perror("src file open error");
return -1;
}
if((destfd=open(argv[2],O_CREAT|O_WRONLY|O_TRUNC,0664))==-1){
perror("dest file open error");
return -1;
}
long size=lseek(srcfd,0,SEEK_END); //获取文件大小,单位:字节
thread t1(task,srcfd,destfd,0,size/2);
thread t2(task,srcfd,destfd,size/2,size-size/2);
t1.join();
t2.join();
return 0;
}
2、使用条件变量完成线程同步,定义三个线程,线程1打印A,线程2打印B,线程3打印C,最终输出的结果为ABCABCABCABC...
#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
using namespace std;
mutex mux;
condition_variable cond;
int current=-1; //current为 0表示打印A,1表示打印B,2表示打印C
void printA(){
while(1){
unique_lock<mutex> lock(mux);
cond.wait(lock,[]{return current==0;});
this_thread::sleep_for(chrono::seconds(1)); //睡眠1s
cout<<"A";
cout.flush(); //手动刷新缓冲区,不然会等到缓冲区满才会输出到屏幕
current=1;
cond.notify_all();
}
}
void printB(){
while(1){
unique_lock<mutex> lock(mux);
cond.wait(lock,[]{return current==1;});
this_thread::sleep_for(chrono::seconds(1)); //睡眠1s
cout<<"B";
cout.flush();
current=2;
cond.notify_all();
}
}
void printC(){
while(1){
unique_lock<mutex> lock(mux);
cond.wait(lock,[]{return current==2;});
this_thread::sleep_for(chrono::seconds(1)); //睡眠1s
cout<<"C";
cout.flush();
current=0;
cond.notify_all();
}
}
int main(int argc, const char *argv[]){
thread a(printA);
thread b(printB);
thread c(printC);
// 此处{ }的作用:创建一个独立作用域
// 限定 std::lock_guard的生命周期,
// 确保锁在 notify_all()之后立即释放。
{
unique_lock<mutex> lock(mux);
current=0;
cond.notify_all();
}
a.join();
b.join();
c.join();
return 0;
}
更多推荐



所有评论(0)