Posix信号量

Posix 信号量

有名信号量

无名信号量

sem_open

sem_init

sem_close

sem_destroy

sem_unlink

sem_wait

sem_post

有名信号量

#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>
sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
int sem_close(sem_t *sem);
int sem_unlink(const char *name);

与Posix类IPC用法类似: 名字以/somename形式标识,且只能有一个/ ,并且总长不能超过NAME_MAX-4 (i.e., 251)。

Posix有名信号量需要用sem_open 函数创建或打开,PV操作分别是sem_wait 和 sem_post,可以使用sem_close 关闭,删除用sem_unlink。

有名信号量用于不需要共享内存的进程间同步(可以通过名字访问), 类似System V 信号量。

匿名信号量

#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_destroy(sem_t *sem);

匿名信号量只存在于内存中, 并要求使用信号量的进程必须可以访问内存; 这意味着他们只能应用在同一进程中的线程, 或者不同进程中已经映射相同内存内容到它们的地址空间中的线程.

匿名信号量必须用sem_init 初始化,sem_init 函数的第二个参数pshared决定了线程共享(pshared=0)还是进程共享(pshared!=0),也可以用sem_post 和sem_wait 进行操作,在共享内存释放前,匿名信号量要先用sem_destroy 销毁。

Posix信号量PV操作

int sem_wait(sem_t *sem);    //P操作
int sem_post(sem_t *sem);   //V操作

wait操作实现对信号量的减1, 如果信号量计数原先为0则会发生阻塞;

post操作将信号量加1, 在调用sem_post时, 如果在调用sem_wait中发生了进程阻塞, 那么进程会被唤醒并且sem_post增1的信号量计数会再次被sem_wait减1;

Posix互斥锁

#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);       //互斥锁初始化, 注意:函数成功执行后,互斥锁被初始化为未锁住状态。
int pthread_mutex_lock(pthread_mutex_t *mutex); //互斥锁上锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);  //互斥锁判断上锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);   //互斥锁解锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);  //消除互斥锁

互斥锁是用一种简单的加锁方法来控制对共享资源的原子操作。这个互斥锁只有两种状态,也就是上锁/解锁,可以把互斥锁看作某种意义上的全局变量。在同一时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程能够对共享资源进行操作。若其他线程希望上锁一个已经被上锁的互斥锁,则该线程就会阻塞,直到上锁的线程释放掉互斥锁为止。可以说,这把互斥锁保证让每个线程对共享资源按顺序进行原子操作。

其中,互斥锁可以分为快速互斥锁(默认互斥锁)、递归互斥锁和检错互斥锁。这三种锁的区别主要在于其他未占有互斥锁的线程在希望得到互斥锁时是否需要阻塞等待。快速锁是指调用线程会阻塞直至拥有互斥锁的线程解锁为止。递归互斥锁能够成功地返回,并且增加调用线程在互斥上加锁的次数,而检错互斥锁则为快速互斥锁的非阻塞版本,它会立即返回并返回一个错误信息。

生产者消费者问题

运用C++, 将缓冲区封装成class Storage

//Storage类设计
class Storage
{
public:Storage(unsigned int _bufferSize);~Storage();void consume(int id);   //消费void produce(int id);   //生产private:// 打印缓冲区状态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::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);//将empty信号量初始化为缓冲区大小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);//获取empty信号量sem_wait(&sem_empty);//获取互斥量pthread_mutex_lock(&mutex);//生产cout << "++ producer " << id << " begin produce "<< ++product_number << " ..." << endl;m_storage[in] = product_number;//打印此时缓冲区状态display(false);in = (in+1)%buffSize;cout << "   producer " << id << " end produce ...\n" << endl;//释放互斥量pthread_mutex_unlock(&mutex);//释放full信号量sem_post(&sem_full);sleep(1);
}
void Storage::consume(int id)
{printf("consumer %d is waiting storage not empty\n", id);//获取full信号量sem_wait(&sem_full);//获取互斥量pthread_mutex_lock(&mutex);//消费int consume_id = m_storage[out];cout << "-- consumer " << id << " begin consume "<< consume_id << " ..." << endl;m_storage[out] = -1;//打印此时缓冲区状态display(true);out = (out+1)%buffSize;cout << "   consumer " << id << " end consume ...\n" << endl;//解锁互斥量pthread_mutex_unlock(&mutex);//释放empty信号量sem_post(&sem_empty);sleep(1);
}
void Storage::display(bool isConsme)
{cout << "states: { ";for (unsigned int i = 0; i < buffSize; ++i){if (isConsme && out == i)cout << '#';else if (!isConsme && in == i)cout << '*';if (m_storage[i] == -1)cout << "null ";elseprintf("%-4d ", m_storage[i]);}cout << "}" << endl;
}
//生产者, 消费者代码实现
//缓冲区
Storage *storage;
//生产者-线程
void *producer(void *args)
{int id = *(int *)args;delete (int *)args;while (1)storage->produce(id);   //生产return NULL;
}
//消费者-线程
void *consumer(void *args)
{int id = *(int *)args;delete (int *)args;while (1)storage->consume(id);   //消费return NULL;
}
//主控线程
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://download.csdn.net/download/hanqing280441589/8444613

Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题相关推荐

  1. linux网络编程之posix 线程(三):posix 匿名信号量与互斥锁 示例生产者--消费者问题

    http://blog.csdn.net/jnu_simba/article/details/9123603 一.posix 信号量 信号量的概念参见这里.前面也讲过system v 信号量,现在来说 ...

  2. Linux多线程实践(6) --Posix读写锁解决读者写者问题

    Posix读写锁 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restr ...

  3. Linux多线程实践(8) --Posix条件变量解决生产者消费者问题

    Posix条件变量 int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); int pthread_co ...

  4. Linux信号量与互斥锁解决生产者与消费者问题

    先来看什么是生产者消费者问题: 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问 ...

  5. 如何用信号量与互斥量解决男女共浴(或过桥问题)

    最近,有一课下作业要求我们使用互斥量或者信号量来解决线程的同步问题(男女浴室问题),没办法,学渣嘛,自己就上网找答案咯,可是搜了N多发现,他们写的基本都是错的(要么线程没控制好,要么产生死锁).无奈. ...

  6. c++ linux 线程等待与唤醒_C++ Linux线程同步机制:POSIX信号量,互斥锁,条件变量...

    线程同步机制:POSIX 信号量,互斥量,条件变量 POSIX 信号量 常用的POSIX 信号量函数为如下5个: sem_init sem_destroy sem_wait sem_trywait s ...

  7. linux网络编程-posix信号量与互斥锁(39)

    -posix信号量信号量 是打开一个有名的信号量 sem_init是打开一个无名的信号量,无名信号量的销毁用sem_destroy sem_wait和sem_post是对信号量进行pv操作,既可以使用 ...

  8. Linux多线程编程---线程间同步(互斥锁、条件变量、信号量和读写锁)

    本篇博文转自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了 ...

  9. Linux多线程实践(六)使用Posix条件变量解决生产者消费者问题

    前面的一片文章我们已经讲过使用信号量解决生产者消费者问题.那么什么情况下我们须要引入条件变量呢? 这里借用  http://www.cnblogs.com/ngnetboy/p/3521547.htm ...

最新文章

  1. (转)数据挖掘——我们能从股市数据得出什么,以及一些算法
  2. [二叉树] 判断一个二叉树是否是平衡(剑指offer39)
  3. linux rmp命令安装包在哪里_rpm命令_Linux rpm 命令用法详解:RPM软件包的管理工具...
  4. 使用Spring Security和OAuth 2.0保护Spring微服务架构
  5. RGB-D dataset
  6. 添加ejs后页面空白解决办法
  7. 商业计划书范文3000_凤城编写商业计划书范文模板格式
  8. 融云 SDK 5.0.0 功能迭代
  9. linux系统下的打印机驱动下载,用于UNIXLinux系统的打印机驱动程序-Lexmark.PDF
  10. 单片机c语言多路ad转换,如何使用单片机实现低成本的高精度AD转换和DA转换
  11. RVB2601应用开发实战系列六:网络播放器设计(二)
  12. MongoTemplate根据时间查询的大坑
  13. 招商银行笔试题之爱吃喵粮的小招喵
  14. 【间歇性努力,不是真正的努力】
  15. DataFrame合并
  16. Android 蓝牙连接
  17. SpringBoot获取自身tomcat端口号的坑 @Value(${server.port})
  18. 月份30或31c语言编程,C语言程序设计上机编程方法.PPT
  19. uniapp Modal自定义弹窗
  20. 要早点进入IT行业不是没道理的

热门文章

  1. 数据结构-线性表之用队列实现栈用栈实现队列
  2. C++11 并发指南四(future 详解一 std::promise 介绍)
  3. Linux日常运维管理技巧(四)文件同步工具-rsync、Linux系统日志、dmesg命令、lastb命令查看登录失败的用户、screen工具虚拟屏幕
  4. JS call()和apply()方法和区别
  5. Python__repr__()方法:显示属性
  6. 一句命令删除docker所有镜像或容器
  7. 面试官:什么是JDK什么是JRE?服务器可以只安装JRE吗?
  8. 深入理解 Node.js 中 EventEmitter源码分析(3.0.0版本)
  9. redis数据结构对象
  10. 【Alpha 冲刺】 1/12