本文共 3046 字,大约阅读时间需要 10 分钟。
Posix信号量是一种进程间同步的机制,广泛应用于多线程程序的通信与调度。Posix信号量与System V信号量类似,主要通过信号量的名字进行操作。名字通常以"/somename"的形式标识,并且只能有一个实例,且名字长度不能超过NAME_MAX-4(即251个字符)。
Posix有名信号量的创建与管理主要通过以下函数完成:
sem_open
:用于打开或创建有名信号量。sem_close
:用于关闭已打开的信号量。sem_unlink
:用于删除已创建的信号量。sem_wait
:用于等待信号量状态改变(P操作)。sem_post
:用于发送信号量变化通知(V操作)。互斥锁是一种简单而高效的互斥机制,用于保护共享资源对原子操作的正确执行。互斥锁在多线程环境中非常有用,确保在同一时间只有一条线程能够访问共享资源。
Posix互斥锁的实现主要通过以下函数完成:
pthread_mutex_init
:用于初始化互斥锁。pthread_mutex_lock
:用于上锁互斥锁。pthread_mutex_trylock
:用于非阻塞上锁。pthread_mutex_unlock
:用于解锁互斥锁。pthread_mutex_destroy
:用于销毁互斥锁。Posix互斥锁可以分为快速互斥锁(默认)、递归互斥锁和检错互斥锁。快速互斥锁是最常用的版本,它在上锁时会导致等待直到互斥锁被释放。递归互斥锁允许线程在拥有互斥锁的同时递归加锁,而检错互斥锁则是非阻塞的版本,它会立即返回错误信息。
在Posix系统中,生产者与消费者问题通常通过信号量和互斥锁来解决。生产者负责向缓冲区中添加产品,消费者则负责从缓冲区中取走产品。为了确保缓冲区的正确使用,生产者和消费者需要对缓冲区进行互斥访问,同时确保缓冲区的充足空间和非空状态。
以下是一个典型的解决方案:
class Storage {public: Storage(unsigned int _bufferSize); ~Storage(); void consume(int id); void produce(int id); void display(bool isConsumer = false);private: unsigned int buffSize; int *m_storage; unsigned short int in; unsigned short int out; unsigned int product_number; sem_t sem_full; sem_t sem_empty; pthread_mutex_t mutex;};
Storage::Storage(unsigned int _bufferSize) : buffSize(_bufferSize), in(0), out(0), product_number(0) { m_storage = new int[buffSize]; for (unsigned int i = 0; i < buffSize; ++i) m_storage[i] = -1; sem_init(&sem_full, 0, 0); sem_init(&sem_empty, 0, buffSize); pthread_mutex_init(&mutex, NULL);}Storage::~Storage() { delete []m_storage; pthread_mutex_destroy(&mutex); sem_destroy(&sem_empty); sem_destroy(&sem_full);}
void Storage::produce(int id) { printf("producer %d is waiting storage not full\n", id); sem_wait(&sem_empty); pthread_mutex_lock(&mutex); m_storage[in] = product_number; in = (in + 1) % buffSize; pthread_mutex_unlock(&mutex); sem_post(&sem_full); sleep(1);}void Storage::consume(int id) { printf("consumer %d is waiting storage not empty\n", id); sem_wait(&sem_full); pthread_mutex_lock(&mutex); m_storage[out] = -1; out = (out + 1) % buffSize; pthread_mutex_unlock(&mutex); sem_post(&sem_empty); sleep(1);}
int main() { int nProducer = 1; int nConsumer = 2; cout << "please input the number of producer: "; cin >> nProducer; cout << "please input the number of consumer: "; cin >> nConsumer; cout << "please input the size of buffer: "; int size; cin >> size; storage = new Storage(size); pthread_t *thread = new pthread_t[nProducer + nConsumer]; for (int i = 0; i < nConsumer; ++i) { pthread_create(&thread[i], NULL, consumer, new int(i)); } for (int i = 0; i < nProducer; ++i) { pthread_create(&thread[nConsumer + i], NULL, producer, new int(i)); } for (int i = 0; i < nProducer + nConsumer; ++i) { pthread_join(thread[i], NULL); } delete storage; delete []thread;}
完整的源代码如上所示。通过合理的信号量初始化、互斥锁管理和线程创建,确保了生产者与消费者问题的高效解决。该方案能够在多线程环境中正确地管理缓冲区,避免数据竞争和死锁问题。
转载地址:http://qmzfk.baihongyu.com/