线程同步机制

发布时间 2023-11-23 10:44:59作者: hellozhangjz

线程之间共享代码、资源、进程(内存)空间、打开文件等。

线程同步机制

互斥锁

互斥锁本质是一个全局变量,其值为0时表示没锁,可以对其进行上锁(+1),而且上锁的操作由硬件和操作系统保证是原子操作,所以不存在两个线程同时上一把锁。其值为1时表示上锁,线程再进行lock操作会阻塞自己,并在互斥锁队列里等待其解锁。被lock()和unlock()包围的代码称之为临界区(critical section)

mutex mxt;
void f(){
  mxt.lock()
	//critical seciotn
	mxt.unlock()
}
thread t1(f);
thread t2(f);

这样就保证同时只有一个线程在访问临界区。

信号量

允许值大于1的互斥锁,down()减1,up()加1,信号量为0时阻塞,大于0被唤醒。

条件变量

也是一个全局变量,作用是使线程阻塞直到等待一个条件成立再继续运行。条件变量是一个队列,线程检测到条件不满足会将自己加入(wait())这个队列里等待被唤醒。另外的线程在改变条件的时候也可以唤醒(signal())队列中的一个或全部线程。注意这个唤醒操作是将线程从条件变量的队列里出列,进入互斥锁的阻塞队列竞争互斥锁,而不是唤醒就直接开始执行下边的代码。没有被唤醒的线程会继续在条件变量的队列中,即使互斥锁被释放也不会去获得锁。

一个典型的条件变量使用:

std::mutex mtx;
std::condition_variable_any cond;

void child() {
  mtx.lock();
  while(not some condiiton) //使用while为了避免“虚假唤醒”
    cond.wait(mtx); // 释放锁,加入条件变量的阻塞队列
  //被唤醒,获得锁,继续执行
  // do somthing
  mtx.unlock();
}

void parent() {
  //do somthing,条件满足
  cond.notify_one(); // 唤醒一个线程
  cond.notify_all(); // 唤醒全部线程
}