线程¶
1. 线程 Thread¶
- 成员变量
由于各个进程是相互独立的,因此不同进程的线程id可能是相同的,因此可以使用进程id来标识线程。
class Thread : boost::noncopyable { private: bool started_; // 线程是否启动 pthread_t pthreadId_; // 线程id pid_t tid_; // 独一无二的进程id ThreadFunc func_; // 线程回调函数 string name_; // 线程名 static AtomicInt32 numCreated_; // 共创建的线程个数 };
-
线程执行 在
start
函数中调用pthread_crate
创建线程,线程函数是startThread
,然后在线程函数startThread
里执行回调函数func_
。由于线程入口函数是void Thread::start() { assert(!started_); started_ = true; pthread_create(&pthreadId_, NULL, &startThread, this); }
static
性质,想要执行回调函数runInThread
,因此在传入参数时候,将线程对象本身传进入才可以在static
函数中调用non-static
函数。+// 实现 void* Thread::startThread(void* obj) { Thread* thread = static_cast<Thread*>(obj); thread->runInThread(); return NULL; } // 调用 pthread_create(&pthreadId_, NULL, &startThread, this);
__thread
关键字 这个关键字使得_thread
定义的POD
类型变量都是线程局部变量,即每个线程都独有一份。
2. 互斥锁 Mutex
¶
MutexLock
实现了对pthread_mutext_t
的封装,管理mutext
的生命周期,不可拷贝。-
MutexLockGuard
使用RAII
封装class MutexLockGuard : boost::noncopyable { public: explicit MutexLockGuard(MutexLock& mutex) : mutex_(mutex) { mutex_.lock(); } ~MutexLockGuard() { mutex_.unlock(); } private: MutexLock& mutex_; // 这里是个引用 };
MutexLockGuard
只是对负责mutex
的lock/unlock
,即不会遗忘对锁的释放而导致死锁,不负责mutex
的生命周期,因此MutexLockGuard
里的成员变量mutex_
是**引用类型**。自动调用析构函数的解锁操作,防止死锁。3. 条件变量
Condition
¶实现对
pthread_cond_t
的封装,内部的mutex
也是**引用类型**,即不负责生命周期。
既可以用于所有子线程等待主线程发起起跑
也可以用于主线程等待子线程初始化完毕才开始工作
-
CountDownLatch
倒计时这个类利用class CountDownLatch : boost::noncopyable { public: explicit CountDownLatch(int count); void wait(); void countDown(); int getCount() const; private: mutable MutexLock mutex_; Condition condition_; int count_; };
Condition
实现所有线程等待某个条件产生再一起运行。具体实现依赖两个wait
和countDown
两个函数实现。 +mutable
关键字 可以让在const
修饰的函数内修改成员变量,主要即针对上面的getCount
函数。