赞
踩
thread ThreadName(ThreadInit)
传入线程的入口函数 T h r e a d I n i t ThreadInit ThreadInit 来创建一个线程 T h r e a d N a m e ThreadName ThreadName。也可以使用类/对象(需重写 operator())、智能指针、带参的方法、类的成员函数或是 lambda 表达式创建一个线程。
thread.join()。会阻塞主线程直到当前线程执行结束后子线程与主线程汇合。
thread.detach()。分离主线程与子线程,主线程运行结束后子线程会在后台执行,执行完成后由运行时库回收相关资源。若主线程中存在实例对象,则在子线程中会调用复制构造函数构建一个新的实例给子线程,因此主线程运行结束并被销毁时不会影响子线程的运行(引用同理)。
thread.joinable()。当一个线程 detach 后不可再 join,所以 join 前可以使用 joinable 判断是否可以 join。
在多线程并发的过程中,多个线程可能会对一块内存同时读/写,可能会导致结果数据与我们期望的数据不一致的问题,因此我们需要通过线程同步的方式来对其进行控制。
交替打印foobar
此处使用一道力扣上的多线程题目作为例题。
给你一个类:
class FooBar {
public void foo() {
for (int i = 0; i < n; i++) {
print("foo");
}
}
public void bar() {
for (int i = 0; i < n; i++) {
print("bar");
}
}
}
两个不同的线程将会共用一个 FooBar 实例:
线程 A 将会调用 foo() 方法,而
线程 B 将会调用 bar() 方法
请设计修改程序,以确保 “foobar” 被输出 n 次。
示例 1:
输入:n = 1
输出:"foobar"
解释:这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 bar() 方法,"foobar" 将被输出一次。
示例 2:
输入:n = 2
输出:"foobarfoobar"
解释:"foobar" 将被输出两次。
依题意需要控制调用两线程的运行顺序,达到控制foo和bar交替输出的效果。
设置一互斥锁后可以使用lock()函数给临界区加锁,并且只有一个线程能获得锁,若当前线程无法上锁,则阻塞;反之会在加锁后继续运行。
此处对 foo 和 bar 分别设置一互斥锁,初始化时对 bar 上锁,因此输出 foo 的线程可以执行,而输出 bar 的线程被阻塞。输出完成 foo 后只打开 bar 的锁,foo 仍处于锁定状态;bar 同理。
class FooBar { private: int n; mutex fooLock, barLock; public: FooBar(int n) { this->n = n; barLock.lock(); } void foo(function<void()> printFoo) { for (int i = 0; i < n; i++) { fooLock.lock(); printFoo(); barLock.unlock(); } } void bar(function<void()> printBar) { for (int i = 0; i < n; i++) { barLock.lock(); printBar(); fooLock.unlock(); } } };
也可以使用 try_lock() 尝试上锁,但 try_lock() 不会阻塞线程,若无法加锁,则返回 false,反之返回true。
类似于智能指针,使用了 RAII 技术,不需要手动 unlock,等离开作用域后就会自动释放。
允许同一线程多次获得互斥锁
获取互斥锁时若超出超时时长,则放弃等待,解除阻塞。
比 lock_guard 效率更低,内存占用更大,但比 unique_lock() 更灵活。同时在第二个参数中指定 adopt_lock(),则创建锁时不会再调用构造函数上锁(但这个锁必须要被锁定过),而仍会调用析构函数解锁。
#include<semaphore.h> class FooBar { private: int n; sem_t mutex_foo, mutex_bar; public: FooBar(int n) { this->n = n; sem_init(&mutex_foo, 0, 1); sem_init(&mutex_bar, 0, 0); } void foo(function<void()> printFoo) { for (int i = 0; i < n; i++) { sem_wait(&mutex_foo); printFoo(); sem_post(&mutex_bar); } } void bar(function<void()> printBar) { for (int i = 0; i < n; i++) { sem_wait(&mutex_bar); printBar(); sem_post(&mutex_foo); } } };
class FooBar { private: int n; atomic<bool> foo_done=false; public: FooBar(int n) { this->n = n; } void foo(function<void()> printFoo) { for (int i = 0; i < n; i++) { while(foo_done) { this_thread::yield(); } printFoo(); foo_done = true; } } void bar(function<void()> printBar) { for (int i = 0; i < n; i++) { while(!foo_done) { this_thread::yield(); } printBar(); foo_done = false; } } };
class FooBar { private: int n; mutex lock; condition_variable cond; bool foo_done = false; public: FooBar(int n) { this->n = n; } void foo(function<void()> printFoo) { for (int i = 0; i < n; i++) { unique_lock<mutex> locker(lock); cond.wait(locker, [&](){return foo_done == false;}); printFoo(); foo_done = true; cond.notify_one(); } } void bar(function<void()> printBar) { for (int i = 0; i < n; i++) { unique_lock<mutex> locker(lock); cond.wait(locker, [&](){return foo_done;}); printBar(); foo_done = false; cond.notify_one(); } } };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。