📜  自旋锁和信号量的区别(1)

📅  最后修改于: 2023-12-03 15:41:24.473000             🧑  作者: Mango

自旋锁和信号量的区别

在并发编程中,自旋锁和信号量都是用来保护共享资源的。虽然它们实现了相似的功能,但是它们的内部机制和使用方式有所不同。

自旋锁

自旋锁是一种基于忙等待的锁,当线程尝试获取锁时,如果发现锁已经被其他线程占用,那么它会一直循环等待,直到被占用的线程释放了锁。虽然自旋锁的实现非常简单,但是它的效率很高,并且能够避免线程的上下文切换。

以下是使用C++11标准提供的自旋锁的示例代码:

#include <iostream>
#include <thread>
#include <mutex>

std::mutex m;

void foo() {
  m.lock();
  std::cout << "Hello from thread " << std::this_thread::get_id() << std::endl;
  m.unlock();
}

int main() {
  std::thread t1(foo);
  std::thread t2(foo);
  t1.join();
  t2.join();
  return 0;
}

在上述代码中,std::mutex就是C++11标准提供的自旋锁的实现。

信号量

信号量是一种基于计数的锁,它可以控制同时访问某一共享资源的线程的数量。当一个线程要访问该资源时,首先需要获取信号量的信号,如果当前信号量的计数器值不为0,则表示可以访问该资源;否则,当前线程会被阻塞,直到其他线程释放该资源。使用信号量可以增加代码的可扩展性,可以灵活地控制并发度。

以下是使用C++11标准提供的信号量的示例代码:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex m;
std::condition_variable cv;
int count = 0;
const int MaxCount = 2;

void foo() {
  std::unique_lock<std::mutex> lock(m);
  cv.wait(lock, []{ return count < MaxCount; });
  count++;
  std::cout << "Hello from thread " << std::this_thread::get_id() << std::endl;
  lock.unlock();
  cv.notify_one();
}

int main() {
  std::thread t1(foo);
  std::thread t2(foo);
  t1.join();
  t2.join();
  return 0;
}

在上述代码中,std::condition_variable就是C++11标准提供的信号量的实现。

自旋锁和信号量的区别

自旋锁是一种忙等待的锁,使用自旋锁时需要占用CPU资源;而信号量是一种基于计数的锁,当资源被占用时,线程会被阻塞,释放CPU资源。

自旋锁适用于锁的占用时间短,资源竞争不激烈的场景;而信号量适用于锁的占用时间长,资源竞争激烈的场景。

自旋锁的实现简单,效率高,但是占用CPU资源;而信号量的实现较为复杂,效率相对较低,但是不占用CPU资源。

另外,自旋锁不支持超时和优先级反转,而信号量支持超时和优先级反转。