同步机制之“信号量和条件变量”的应用总结

1. 信号量与条件变量的区别

应用场景: 信号量即可用于进程间同步,也可用于线程间同步; 条件变量只能用于线程间。

用法上: 条件变量需要和互斥锁配合使用,而信号量之间使用就可以,所以信号量更像是条件变量和互斥锁的组合,所以必然的条件变量的使用会比信号量的使用更加灵活。毕竟,后出现的技术比之前的必然要有先进性(能解决特定的需求),才有其存在的意义。

底层实现上:信号量内部以计数方式来判定是否阻塞(有累计数量的功能),计数单次加减1即每次只能唤醒一个进程或线程。而条件变量以“自定义条件”来判定是否阻塞(优点来了),那么它就可以唤醒一个线程或所有线程(notify_all类似广播)。

信号量具体使用:

1、C语言信号量接口参见 #include<semaphore.h>

(1) 信号量的创建接口,int sem_init(sem_t *sem,int pshared,unsigned int value);

调用成功时返回0,失败返回-1.

参数一: 信号对象指针

参数二: 设置它的进程间共享选项,0为不共享,其余则共享;

参数三:设置信号量初始值,一般填0,即开始默认阻塞(当信号量值小于、等于0则阻塞)。

(2) 信号量的等待接口,int sem_wait(sem_t *sem);  

如果信号量的值大于0,将信号量的值减1,立即返回。如果信号量的值为0或小于0,则线程阻塞。  调用成功时返回0,失败返回-1.

(3)信号量值加1接口,int sem_post(sem_t *sem);  

释放信号量,让信号量的值加1。 调用成功时返回0,失败返回-1.

(4)信号量的清理接口(相对sem_init而言),int sem_destroy(sem_t *sem);

成功时返回0,失败时返回-1.

示例:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#include <semaphore.h>

  sem_t g_sem;///

  void func1(void* arg)
  {
      sem_wait(&sem); /线程1初始阻塞
      int *running=arg;
      printf("thread running1\n");
      printf("%d\n",*running);
  }

  void func2(void* arg)
  {
      printf("pthread2 running\n");
      sem_post(&sem); //线程2增加信号量,致使线程1阻塞被唤醒以执行后续代码
  }

  int main()
  {
      sem_init(&g_sem,0,0);信号量初始化为本进程内多线程使用,初始阻塞
      pthread_t thread[2];
      int  a = 1;
      pthread_create(&(thread[0]),NULL,(void*)func1,(void*)&a);
      sleep(3);
      pthread_create(&(thread[1]),NULL,(void*)func2,(void*)&a);
      pthread_join(thread[0],NULL);
      pthread_join(thread[1],NULL);
      sem_destroy(&sem); //信号量销毁

      return 0;
  }

2、C++  --std=c++20 信号量 counting_semaphore ,参见 #include <semaphore>

#include <iostream>
#include <thread>
#include <semaphore>
#include <unistd.h>

using namespace std;

std::counting_semaphore streams_sem{0};

void custom_thread(){
  while (1){
    streams_sem.acquire();
    std::cout << "shopping!\n";
    usleep(50000);
  }
}

class Prod{
public:
    Prod(int nCnt){  m_needProCnt = nCnt; }
    void product() {
        int num = 0;
        while(num<m_needProCnt){
           cout<<" product production"<<endl;
           streams_sem.release();
           ++num;
        }

    }
    void inner_custom(){
       while(1) {
        if ( !streams_sem.try_acquire() )
        {
          cout<<"want? no way"<<endl;
          break;
        }
        std::cout << "want inner shopping!\n";
        usleep(100000);
       }
    }
private:
    int m_needProCnt;
};

int main(int argc, char const* argv[]){
  std::thread t1(custom_thread);
  t1.detach();
  Prod prod(20);
  std::thread t2(&Prod::product, &prod);
  std::thread t3(&Prod::inner_custom, &prod);
  t2.join();
  t3.join();

  return 0;
}

条件变量具体使用:

template <typename T>
class BlockQue {
public:
	BlockQue():m_end(false){}
	~BlockQue(){
		endBlockQue();
	}
    void addTask(T data){
		m_tasks.push(data);
		m_task_cv.notify_all();
	}
	void clearTask(bool del){
		//CAutoLock lock(m_mutexClr);
		while(!m_tasks.empty()){
			T data = std::move(m_tasks.front());
			m_tasks.pop();
			if(del){
				delete data;
			}
		}
	} 
	bool isEmpty(){
		return m_tasks.empty();
	}
	int size(){
		return m_tasks.size();
	}
    int getTask(T& data){
		//CAutoLock lock(m_mutexClr);
		std::unique_lock<std::mutex> lock{ m_lock };
		m_task_cv.wait(lock, [this]{
			return m_end.load() || !m_tasks.empty();//true则不阻塞
		});
		if (m_tasks.empty()){
			return -1;
		}
		data = std::move(m_tasks.front());
		m_tasks.pop();
		return 0;
	}

	void initBlockQue() {
		m_end.store(false);
	}
	void endBlockQue(){
		if (!m_end.load()){
			m_end.store(true);
			m_task_cv.notify_all();
		}
	}
private:
	std::atomic<bool> 		m_end;
    std::condition_variable m_task_cv;
	std::queue<T> 	m_tasks;
	std::mutex 		m_lock;
	//CMutexEx 		m_mutexClr;
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

字正腔圆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值