📅  最后修改于: 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资源。
另外,自旋锁不支持超时和优先级反转,而信号量支持超时和优先级反转。