网站建设用什么视频播放器,wordpress后台经常504,思帽西宁网站建设,百度分享wordpress插件线程支持库包含了线程#xff0c;互斥锁#xff0c;线程条件变量(class thread)#xff0c;定义于thread 线程提供一个并发的实例#xff0c;需要对应一个“线程函数” 线程的主要任务就是去执行这个线程函数 既然线程需要提供一个线程函数#xff0c… 线程支持库包含了线程互斥锁线程条件变量(class thread)定义于thread 线程提供一个并发的实例需要对应一个“线程函数” 线程的主要任务就是去执行这个线程函数 既然线程需要提供一个线程函数在线程实例化的时候需要一个线程函数 构造一个线程类的对象需要提供一个参数(线程函数)C的线程类就是包装了POSIX标准的线程接口所以在编译的时候需要链接多线程库 -lpthread 最基本的用法 thread t{线程函数线程函数的参数......}// 实例化一个线程对象创建成功之后就会自动运行 t.join()// 等待线程退出 01 线程类的用法(创建一个线程让新创建的线程完成指定的功能) (1) 线程函数是全局函数 #include iostream
#include threadusing namespace std;// 全局的线程函数(按值传递)
void print_arg(int a) {int c 10;while (c--) {cout a: a endl;// 线程休眠一段时间this_thread::sleep_for(1s);}
}// 全局的线程函数(按引用传递)
void print_arg1(int a) { // a成为你实际传入的参数的别名int c 10;while (c--) {cout a: a endl;//线程休眠一段时间this_thread::sleep_for(1s);}
}int main() {// 实例化一个线程对象,自动开始运行// thread t{线程函数, 线程函数的参数};int n 10;// thread t{print_arg, n}; // 创建一个线程,按值传递参数thread t{print_arg1, std::ref(n)}; // 创建一个线程,按引用传递参数// 传参的时候,指定n以引用的方式传递给线程的构造函数/*thread(线程函数地址, int x n) { // 线程的构造函数pthread_create(...线程函数地址x);}*/// 完成其他的任务int c 10;while (c--) {cout hello endl;// 线程休眠一段时间this_thread::sleep_for(1s);}// 等待线程结束t.join(); // 阻塞cout n: n endl;return 0;
} (2) 线程函数是类的static函数 类的static函数 a. 可以通过类名调用 b. 没有this指针 c. 只能访问类的静态成员(不能访问类的非static成员) 使用方式 thread t{类名::静态成员函数名线程函数的参数} // 线程函数是类的static函数#include iostream
#include threadusing namespace std;class A {public:// 线程函数(按值传递)static void print_arg(int a) {int c 10;while (c--) {cout a: a endl;// 线程休眠一段时间this_thread::sleep_for(1s);}}// 线程函数(按引用传递)static void print_arg1(int a) { // a成为你实际传入的参数的别名int c 10;while (c--) {cout a: a endl;// 线程休眠一段时间this_thread::sleep_for(1s);}}
};int main() {// 实例化一个线程对象,自动开始运行// thread t{线程函数, 线程函数的参数};int n 10;// A::print_arg()// thread t{A::print_arg, n}; // 创建一个线程,按值传递参数thread t{A::print_arg1, std::ref(n)}; // 创建一个线程,按引用传递参数// 传参的时候,指定n以引用的方式传递给线程的构造函数// 完成其他的任务int c 10;while (c--) {cout hello endl;// 线程休眠一段时间this_thread::sleep_for(1s);}// 等待线程结束t.join(); // 阻塞cout n: n endl;return 0;
} (3) 线程函数是类的普通成员函数 普通的全局函数和静态函数都可以直接调用不需要通过对象但是类的普通成员函数不能直接调用必须通过对象调用(因为有一个隐式的参数this) 所以当一个类的非静态成员函数作为线程函数时我们需要传递一个该类的对象的地址作为this指针的实参 语法 thread t{类名::成员函数名该类对象的地址线程函数的参数} // 线程函数是类的非static函数#include iostream
#include threadusing namespace std;class A {public:// 线程函数(按值传递)void print_arg(int a) {int c 10;while (c--) {cout a: a endl;// 线程休眠一段时间this_thread::sleep_for(1s);}}// 线程函数(按引用传递)void print_arg1(int a) { // a成为你实际传入的参数的别名int c 10;while (c--) {cout a: a endl;// 线程休眠一段时间this_thread::sleep_for(1s);}}
};int main() {// 实例化一个线程对象,自动开始运行// thread t{线程函数, 线程函数的参数};int n 10;A a; // 实例化一个对象// a.print_arg(n) ----- print_arg(a, n)// thread t{A::print_arg, a, n}; // 创建一个线程,按值传递参数thread t{A::print_arg1, a, std::ref(n)}; // 创建一个线程,按引用传递参数// 传参的时候,指定n以引用的方式传递给线程的构造函数// 完成其他的任务int c 10;while (c--) {cout hello endl;// 线程休眠一段时间this_thread::sleep_for(1s);}// 等待线程结束t.join(); // 阻塞cout n: n endl;return 0;
} 以上三种就是线程最普通的用法 02 线程互斥锁(mutex) 线程互斥锁是用来避免多个并发实例对共享资源的访问产生竞争定义于头文件mutex class mutex; class timed_mutex; std::mutex 既不可以复制也不可以移动(删除了operator也没有实现移动构造函数) 默认构造函数可以初始化一个锁对象默认是处于解锁状态的 函数 lock 上锁阻塞到获取锁 try_lock 尝试获取锁获取失败则返回false unlock 解锁 用法 mutex m// 实例化一个锁对象 m.lock(); // 访问共享资源前上锁 m.try_lock(); ......; // 访问共享资源的代码(临界区) m.unlock(); // 访问完共享资源后解锁 #include iostream
#include thread
#include mutexusing namespace std;mutex m; // 全局的锁// 全局的共享资源
int x 0;// 是一个不可重入的函数
void add_x() {int c 1000000;while (c--) {// while (!m.try_lock()); // 上锁m.lock();x; // 共享资源m.unlock(); }
}int main() {// 实例化一个线程对象,自动开始运行thread t1{add_x}; thread t2{add_x}; // 等待线程结束t1.join(); // 阻塞t2.join(); // 阻塞cout x: x endl;return 0;
} mutextimed_mutex ...... 可以单独使用但是可能会遇到一些问题 如 (1) 程序员不注意造成了带锁退出 ------ deadlock xxx() { m.lock(); ...... if (...) { return ; } m.unlock(); } (2) 同时获取多个锁推进的顺序不一样 xxx() { m1.lock(); m2.lock(); ...... ...... m2.unlock(); m1.unlock(); } yyy() { m2.lock(); m1.lock(); ...... ...... m1.unlock(); m2.unlock(); } 基于这样的原因C标准库中提供了一些互斥锁的包裹类 常用的是 std::lock_guardstd::mutex guard{m}; std::unique_lockstd::mutex lock{m}; 可以自动的管理指定的锁在代码作用域结束后可以自动的释放指定的锁可以防止带锁退出 如 mutex m; // 普通的互斥锁默认是处于解锁状态的 { // 描述的是一个作用域范围 std::lock_guardstd::mutex guard{m}; // 使用一个管理对象guard管理锁m // ...... 临界区代码 return ; } 上面的代码是使用lock_guard类型去管理m这个锁当构造guard的时候自动的给m表示的锁上锁当guard超出作用域范围后guard管理的锁自动的解锁 #include iostream
#include thread
#include mutexusing namespace std;mutex m; // 全局的锁// 全局的共享资源
int x 0;// 是一个不可重入的函数
void add_x() {int c 1000000;while (c--) {lock_guardmutex g{m}; // 使用包裹类对象g管理m表示的锁x; // 共享资源}
}int main() {// 实例化一个线程对象,自动开始运行thread t1{add_x}; thread t2{add_x}; // 等待线程结束t1.join(); // 阻塞t2.join(); // 阻塞cout x: x endl;return 0;
} unique_lock是lock_guard的升级版提供了额外的接口 也能够在超出作用域范围之后自动的释放管理的锁 用于指定锁定策略的标签常量(常量) defer_lock try_to_lock adopt_lock 但是还有一些额外的功能 如 1. 同时获取多个锁 mutex m1m2; { // 希望同时获取m1和m2要么都获取成功要么都不成功 // 创建之后实际上没有获取锁 std::unique_lockstd::mutex lock1{m1, std::defer_lock}; std::unique_lockstd::mutex lock2{m2, std::defer_lock}; // 同时获取lock1和lock2表示的两个锁 std::lock(lock1, lock2); // 同时获取 // ......临界区代码 } 2. 管理锁住的粒度(操作共享资源的代码块的大小) void add_x1() { int c 100000; // explicit unique_lock( mutex_type m); // 没加参数表示构造的时候获取锁 std::unique_lockstd::mutex lock{m}; // 构造的时候上锁 while (c--) { x; lock.unlock(); // 手动释放锁 scanf(......); lock.lock(); // 手动加锁 } } 03 线程条件变量 线程可以等待一个程序员人为设置的一个条件 条件不满足的时候线程可以等待这个条件当条件满足的时候线程可以继续往下运行 定义于头文件 condition_variable class condition_variable 能够阻塞一个线程或者同时阻塞多个线程直到条件变量表示的”条件“成立并且被其他地方通知 用于”生产者-消费者“模式 #include iostream
#include thread
#include mutex
#include condition_variableusing namespace std;mutex m; // 全局的锁
condition_variable cond; // 条件变量,表示程序员抽象出来的一个条件// 全局的共享资源
int x 0;// 生产者函数
void add_x() {while (1) {// while (!m.try_lock()); // 上锁m.lock();x; // 生产数据cout 生产者: x endl;if (x 5) { // 表示满足消费条件,应该通知消费者消费数据cout 通知消费者! endl;cond.notify_all(); // 通知所有等待的线程}m.unlock();this_thread::sleep_for(1s); }
}// 生产者函数
// void add_x() {
// while (1) {
// // while (!m.try_lock()); // 上锁
// m.lock();
// x; // 生产数据
// cout 生产者: x endl;
// m.unlock();
// this_thread::sleep_for(1s);
// }
// }// 消费者函数
void delete_x() {while (1) {// 没加参数表示构造的时候获取锁unique_lockmutex lk{m}; // 构造的时候上锁if (x 5) {x x - 5; // 消费数据cout 消费者: x endl;} else {cout 我在浪费CPU! endl;cout 等待一个条件 endl;cond.wait(lk); // 原子的解锁lock,阻塞等待cond表示的条件}}
}// 消费者函数
// void delete_x() {
// while (1) {
// // while (!m.try_lock());
// m.lock();
// if (x 5) {
// x x - 5; // 消费数据
// cout 消费者: x endl;
// } else {
// cout 我在浪费CPU! endl;
// }
// m.unlock();
// this_thread::sleep_for(1s);
// }
// }int main() {// 实例化一个线程对象,自动开始运行thread t1{add_x}; thread t2{delete_x}; // 等待线程结束t1.join(); // 阻塞t2.join(); // 阻塞return 0;
}