1、简介

  POSIX信号量是一个sem_t 类型的变量,但POSIX 有两种信号量的实现机制:无名信号量和命名信号量。无名信号量可以用在共享内存的情况下,

  比如实现进程中各个线程之间的互斥和同步。命名信号量通常用于不共享内存的情况下,比如不共享内存的进程之间。

1.1POSIX 无名信号量

  在使用信号量之前,必须对其进行初始化。sem_init 函数初始化指定的信号量:

  int sem_init (sem_t *sem, int pshared, unsigned int value)

  无名信号量(也称为基于内存的信号量)sem初始化,设置共享选项pshared,并指定一个整数类型的初始值为value。pshared参数控制着信号量的类型。

  如果 pshared的值是0,就表示它是当前里程的局部信号量;否则,其它进程就能够共享这个信号量。

  intsem_destroy(sem_t *sem);

  释放无名信号量。

1.2POSIX 命名信号量

  之所以称为命名信号量,是因为它有一个名字、一个用户ID、一个组ID和权限,这些是提供给不共享内存的那些进程使用命名信号量的接口。命名信号量的名字是一个遵守路径名构造规则的字符串。

  sem_t*sem_open(const char *name,int oflag,mode_t mode,unsigned int value);

  参数 name 是一个标识信号量的字符串。参数oflag 用来确定是创建信号量还是连接已有信号量。如果设置了oflag 的O_CREAT 比特位,则会创建一个新的信号量。

  有名信号量(返回值)的创建和初始化。出错时返回为SEM_FAILED。

  int sem_close(sem_t *sem);

  单个程序可以用sem_close函数关闭命名信号量,但是这样做并不能将信号量从系统中删除,因为命名信号量在单个程序的执行之外是具有持久性的。

  当进程调用_exit、exit、exec 或从main 返回时,进程打开的命名信号量同样会被关闭。对应有名信号量的关闭,注意不是销毁,是关闭。

  int sem_unlink(count char*name);

  sem_unlink函数用于在所有进程关闭了命名信号量之后,将信号量从系统中删除。对应有名信号量的销毁,每个信号都有一个引用计数器记录当前的打开次数,

  sem_unlink必须等待这个数为0时才能把name所指的信号灯从文件系统中删除。也就是要等待最后一个sem_close发生

1.3信号量的操作函数为sem_post、sem_wait、sem_trywait:

  int sem_wait(sem_t *sem);

  int sem_trywait(sem_t *sem);

  对应信号量的P操作。 sem_wait和sem_trywait的差别是:当所指定信号灯的值已是0时,后者并不将调用线程投入睡眠。相反,他返回一个EAGAIN错误。

  int sem_post(sem_t *sem);

  int sem_getvalue(sem_t *sem,int *valp);

  对应信号量的V操作。

2、互斥锁是通过锁的机制来实现线程间的同步问题。互斥锁的基本流程为:

  初始化一个互斥锁:pthread_mutex_init()函数

  加锁:pthread_mutex_lock()函数或者pthread_mutex_trylock()函数

  对共享资源的操作

  解锁:pthread_mutex_unlock()函数

  注销互斥锁:pthread_mutex_destory()函数

  其中,在加锁过程中,pthread_mutex_lock()函数和pthread_mutex_trylock()函数的过程略有不同:

    当使用pthread_mutex_lock()函数进行加锁时,若此时已经被锁,则尝试加锁的线程会被阻塞,直到互斥锁被其他线程释放,当pthread_mutex_lock()函数有返回值时,说明加锁成功;

    而使用pthread_mutex_trylock()函数进行加锁时,若此时已经被锁,则会返回EBUSY的错误码。

  同时,解锁的过程中,也需要满足两个条件:

    解锁前,互斥锁必须处于锁定状态;

    必须由加锁的线程进行解锁。

  当互斥锁使用完成后,必须进行清除。

  初始化互斥锁

  int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);

  功能:初始化一个互斥锁。

  参数:mutex:互斥锁地址。类型是 pthread_mutex_t 。
       attr:设置互斥量的属性,通常可采用默认属性,即可将 attr 设为 NULL。

  可以使用宏 PTHREAD_MUTEX_INITIALIZER 静态初始化互斥锁,比如:

     pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;

  这种方法等价于使用 NULL 指定的 attr 参数调用 pthread_mutex_init() 来完成动态初始化,不同之处在于 PTHREAD_MUTEX_INITIALIZER 宏不进行错误检查。

  返回值:成功:0,成功申请的锁默认是打开的。失败:非 0 错误码

  上锁

  int pthread_mutex_lock(pthread_mutex_t *mutex); 

  功能:对互斥锁上锁,若互斥锁已经上锁,则调用者一直阻塞,直到互斥锁解锁后再上锁。

  参数:mutex:互斥锁地址。

  返回值:成功:0,失败:非 0 错误码

  int pthread_mutex_trylock(pthread_mutex_t *mutex);

  调用该函数时,若互斥锁未加锁,则上锁,返回 0;若互斥锁已加锁,则函数直接返回失败,即 EBUSY。

  解锁

  int pthread_mutex_unlock(pthread_mutex_t * mutex);

  功能:对指定的互斥锁解锁。

  参数:mutex:互斥锁地址。

  返回值:成功:0,失败:非 0 错误码

  销毁互斥锁

  int pthread_mutex_destroy(pthread_mutex_t *mutex);

  功能:销毁指定的一个互斥锁。互斥锁在使用完毕后,必须要对互斥锁进行销毁,以释放资源。

  参数:mutex:互斥锁地址。

  返回值:成功:0,失败:非 0 错误码

#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <semaphore.h> #include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while() #define CONSUMERS_COUNT 1
#define PRODUCERS_COUNT 1
#define BUFFSIZE 10 int g_buffer[BUFFSIZE]; unsigned short in = ;
unsigned short out = ;
unsigned short produce_id = ;
unsigned short consume_id = ; sem_t g_sem_full;
sem_t g_sem_empty;
pthread_mutex_t g_mutex; pthread_t g_thread[CONSUMERS_COUNT+PRODUCERS_COUNT]; void* consume(void *arg)
{
int num = (int)arg;
int i;
while ()
{
printf("%d wait buffer not empty\n", num);
sem_wait(&g_sem_empty);
pthread_mutex_lock(&g_mutex);
//消费产品
for (i=; i<BUFFSIZE; i++)
{
printf("%02d ", i);
if (g_buffer[i] == -)
printf("%s", "null");
else
printf("%d", g_buffer[i]); if (i == out)
printf("\t<--consume"); printf("\n");
} consume_id = g_buffer[out];
printf("%d begin consume product %d\n", num, consume_id);
g_buffer[out] = -;
out = (out + ) % BUFFSIZE;
printf("%d end consume product %d\n", num, consume_id); pthread_mutex_unlock(&g_mutex);
sem_post(&g_sem_full); sleep();
}
return NULL;
} void* produce(void *arg)
{
int num = (int)arg;
int i;
while ()
{
printf("%d wait buffer not full\n", num);
sem_wait(&g_sem_full);
pthread_mutex_lock(&g_mutex);
//生产产品的代码
for (i=; i<BUFFSIZE; i++)
{
printf("%02d ", i);
if (g_buffer[i] == -)
printf("%s", "null");
else
printf("%d", g_buffer[i]); if (i == in)
printf("\t<--produce"); printf("\n");
} printf("%d begin produce product %d\n", num, produce_id);
g_buffer[in] = produce_id;
in = (in + ) % BUFFSIZE;
printf("%d end produce product %d\n", num, produce_id++);
pthread_mutex_unlock(&g_mutex);
sem_post(&g_sem_empty); sleep();
}
return NULL;
} int main(void)
{
int i;
for (i=; i<BUFFSIZE; i++)
g_buffer[i] = -; sem_init(&g_sem_full, , BUFFSIZE);
sem_init(&g_sem_empty, , ); pthread_mutex_init(&g_mutex, NULL); for (i=; i<CONSUMERS_COUNT; i++)
pthread_create(&g_thread[i], NULL, consume, (void*)i); for (i=; i<PRODUCERS_COUNT; i++)
pthread_create(&g_thread[CONSUMERS_COUNT+i], NULL, produce, (void*)i); for (i=; i<CONSUMERS_COUNT+PRODUCERS_COUNT; i++)
pthread_join(g_thread[i], NULL); sem_destroy(&g_sem_full);
sem_destroy(&g_sem_empty);
pthread_mutex_destroy(&g_mutex); return ;
}

参考:http://blog.csdn.net/tennysonsky/article/details/46494077

posix信号量与互斥锁的更多相关文章

  1. linux网络编程之posix信号量与互斥锁

    继上次学习了posix线程之后,这次来讨论一下posix信号量与互斥锁相关的知识: 跟posix消息队列,共享内存的打开,关闭,删除操作一样,不过,上面的函数是对有名信号量进行操作,通过man帮助可以 ...

  2. POSIX信号量与互斥锁实现生产者消费者模型

    posix信号量 Link with -lpthread. sem_t *sem_open(const char *name, int oflag);//打开POSIX信号量 sem_t *sem_o ...

  3. 第三十九章 POSIX信号量与互斥锁

    POSIX信号量相关函数 sem_open 功能: initialize and open a named semaphore 原型: sem_t *sem_open(const char *name ...

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

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

  5. posix 匿名信号量与互斥锁 示例生产者--消费者问题

    一.posix 信号量 信号量的概念参见这里.前面也讲过system v 信号量,现在来说说posix 信号量. system v 信号量只能用于进程间同步,而posix 信号量除了可以进程间同步,还 ...

  6. Linux——临界段,信号量,互斥锁,自旋锁,原子操作

    一. linux为什么需要临界段,信号量,互斥锁,自旋锁,原子操作? 1.1. linux内核后期版本是支持多核CPU以及抢占式调度.这里就存在一个并发,竞争状态(简称竟态). 1.2. 竞态条件 发 ...

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

    Posix信号量 Posix 信号量 有名信号量 无名信号量 sem_open sem_init sem_close sem_destroy sem_unlink sem_wait sem_post ...

  8. 【linux】系统编程-6-POSIX标准下的信号量与互斥锁

    目录 前言 8. POSIX信号量 8.1 概念 8.2 POSIX无名信号量 8.3 POSIX有名信号量 8.4 POPSIX信号量与system V信号量的区别 9. POSIX互斥锁 9.1 ...

  9. ZooKeeper 分布式锁 Curator 源码 04:分布式信号量和互斥锁

    前言 分布式信号量,之前在 Redisson 中也介绍过,Redisson 的信号量是将计数维护在 Redis 中的,那现在来看一下 Curator 是如何基于 ZooKeeper 实现信号量的. 使 ...

随机推荐

  1. poj-2514-模拟

    http://poj.org/problem?id=2514 Ridiculous Addition Time Limit: 1000MS   Memory Limit: 65536K Total S ...

  2. 鼠标放上改变Button的大小

     private void enterBtn_MouseLeave(object sender, MouseEventArgs e)         {             enterBtn.Wi ...

  3. 2017-5-5/PHP实现负载均衡的加权轮询

    1. 负载均衡算法有哪些? 轮询法:将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载. 随机法:通过系统的随机算法,根据后端服务器的列表 ...

  4. nodejs--路径问题

    在读写模块中,需要引入读写文件,此时需要注意路径问题.Node.js中为我们提供了两个参数:__dirname和__filename. __dirname:全局变量,存储的是文件所在的文件目录 __f ...

  5. Lamda 表达式里的Join和GroupJoin的区别, 如何实现SQL的Left Join效果

    例如,可以将产品表与产品类别表相联接,得到产品名称和与其相对应的类别名称 db.Products .Join ( db.Categories, p => p.CategoryID, c => ...

  6. springboot aop 自定义注解方式实现一套完善的日志记录(完整源码)

    https://www.cnblogs.com/wenjunwei/p/9639909.html https://blog.csdn.net/tyrant_800/article/details/78 ...

  7. 2-Servlet和servletContext

    2018-08-09   22:34 * Servlet(好好学)  * 动态WEB的资源.   * 什么是Servlet    * 实现Servlet接口,重写5个方法.           * S ...

  8. learning ddr mode register MR2

  9. mips编译器交叉编译openssl

    1.下载源码: git clone https://github.com/openssl/openssl.git 2. 配置生成Makefile ./config  no-asm shared --p ...

  10. python3 线程池-threadpool模块与concurrent.futures模块

    多种方法实现 python 线程池 一. 既然多线程可以缩短程序运行时间,那么,是不是线程数量越多越好呢? 显然,并不是,每一个线程的从生成到消亡也是需要时间和资源的,太多的线程会占用过多的系统资源( ...