线程同步---信号量(无名)

1. 有名信号量&无名信号量

在POSIX标准中,信号量分两种,一种是无名信号量,一种是有名信号量。无名信号量只用于线程间的同步,有名信号量只用于进程间通信。信号量是属于POSIX:SEM的,不是属于POSIX:THR的,需要的文件头是<semaphore.h>。两者的共同点都是相当于计数器,用于限制多个进程对有限共享资源的访问

2.  相关函数

1)创建信号量

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

sem        - 信号量ID,输出。

pshared - 一般取0,表示调用进程的信号量。  非0表示该信号量可以共享内存的方式, 为多个进程所共享(Linux暂不支持)。

value      - 信号量初值。

2)信号量操作函数

int sem_post (sem_t* sem);// 信号量加1
int sem_wait (sem_t* sem);//信号量减1,不够减即阻塞
int sem_trywait (sem_t* sem);// 信号量减1,不够减即返回-1,errno为EAGAIN
int sem_timedwait (sem_t* sem, const struct timespec* abs_timeout);// 信号量减1,不够减即阻塞,直到abs_timeout超时返回-1,errno为ETIMEDOUT
struct timespec {
    time_t tv_sec;  // Seconds
    long   tv_nsec; // Nanoseconds [0 - 999999999]
};
int sem_getvalue(sem_t *sem, int *sval);//把 sem 指向的信号量当前值放置在 sval 指向的整数上

3) 销毁信号量

int sem_destroy (sem_t* sem);

3. 和互斥量的区别与联系:

互斥量任何时候都只允许一个线程访问共享资源, 而信号量则允许最多value个线程同时访问共享资源,当value为1时,与互斥量等价。

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

unsigned int g_cn = 0;

sem_t g_sem;

void* thread_proc (void* arg) {
	unsigned int i;
	for (i = 0; i < 100000; i++) {
		sem_wait (&g_sem);
		g_cn++;
		sem_post (&g_sem);
	}

	return NULL;
}

int main (void) {
	size_t i;
	pthread_t tids[2];
	int error;

	sem_init (&g_sem, 0, 1);

	for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++)
		if ((error = pthread_create (&tids[i], NULL, thread_proc,
			NULL)) != 0) {
			fprintf (stderr, "pthread_create: %s\n", strerror (error));
			return -1;
		}

	for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++)
		if ((error = pthread_join (tids[i], NULL)) != 0) {
			fprintf (stderr, "pthread_join: %s\n", strerror (error));
			return -1;
		}

	sem_destroy (&g_sem);
	printf ("g_cn = %u\n", g_cn);
	return 0;
}

结果无论运行多少次,一直为20万

4.  模拟实习一个连接池问题,用来对有限资源的访问:

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

#define MAX_CONNS 5  // 最大连接数
#define MAX_USERS 50 // 最大用户数

sem_t g_sem;

void* thread_user (void* arg) {
	pthread_t tid = pthread_self ();

	int sval;
	sem_getvalue (&g_sem, &sval);
	printf ("%lu线程:等待数据库连接(还剩%d个空闲连接)...\n", tid, sval);

	sem_wait (&g_sem);
	sem_getvalue (&g_sem, &sval);
	printf ("%lu线程:获得数据库连接(还剩%d个空闲连接)!\n", tid, sval);

	usleep (1000000);

	sem_post (&g_sem);
	sem_getvalue (&g_sem, &sval);
	printf ("%lu线程:释放数据库连接(还剩%d个空闲连接)。\n", tid, sval);

	return NULL;
}

int main (void) {
	size_t i;
	pthread_t tids[MAX_USERS];
	int error;

	sem_init (&g_sem, 0, MAX_CONNS);
    //创建50个线程
	for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++)
		if ((error = pthread_create (&tids[i], NULL, thread_user,
			NULL)) != 0) {
			fprintf (stderr, "pthread_create: %s\n", strerror (error));
			return -1;
		}
    //回收线程
	for (i = 0; i < sizeof (tids) / sizeof (tids[0]); i++)
		if ((error = pthread_join (tids[i], NULL)) != 0) {
			fprintf (stderr, "pthread_join: %s\n", strerror (error));
			return -1;
		}
    //销毁信号量
	sem_destroy (&g_sem);
	return 0;
}

部分结果图:

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-07-30 18:53:20

线程同步---信号量(无名)的相关文章

经典线程同步 信号量Semaphore

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> 前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore常用有三个函数,使用很方便.下面是这几个函数的原型和使

秒杀多线程第八篇 经典线程同步 信号量Semaphore

版权声明:本文为博主原创文章,未经博主允许不得转载. 阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> 前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore

Linux线程同步---信号量

首先讲一下线程同步信号量的几个关键步骤! 1.定义并初始化信号量. (1) sem_t bin_sem; (2)  res = sem_init(&bin_sem,0,0); 详细步骤可以查看man帮助页面 2.使用信号量 (1) 信号量加1操作.sem_post(&bin_sem); (2) 信号量等待并减1操作.sem_wait(&bin_sem); 初始化后一般处于等待状态,执行某个操作后加1,而另个一个操作执行前进行等待操作.如果有多个线程,通常是一个线程进行加1操作,另外

线程同步——内核对象实现线程同步——信号量

1 /* 2 3 信号量内核对象 4 信号量与其它内核量相同,包含一个使用计数,除此之外还包含两个量. 5 一个最大资源计数和一个当前资源计数. 6 信号量规则如下: 7 如果当前资源计数大于0,那么信号量处于触发状态. 8 如果当前资源计数等于0,那么信号量处于未触发状态. 9 系统绝不会让当前资源计数变为负数. 10 当前资源计数绝不会大于最大资源计数. 11 12 下面我们看一下信号量的创建函数 13 HANDLE CreateSemaphore( 14 LPSECURITY_ATTRIB

linux系统编程:线程同步-信号量(semaphore)

线程同步-信号量(semaphore) 生产者与消费者问题再思考 在实际生活中,只要有商品,消费者就可以消费,这没问题.但生产者的生产并不是无限的,例如,仓库是有限的,原材料是有限的,生产指标受消费指标限制等等.为了进一步,解决好生产者与消费者问题,引入信号量进机制. 信号量 信号量(semaphore)是互斥量的升级版:互斥量的状态为0或1,而信号量可以为n.也就是说,使用互斥量时,最多允许一个线程进入关键区,而信号量允许多个,具体值是信号量当前的内部值. 相关函数 sem_t //信号量类型

转---秒杀多线程第八篇 经典线程同步 信号量Semaphore

阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> 前面介绍了关键段CS.事件Event.互斥量Mutex在经典线程同步问题中的使用.本篇介绍用信号量Semaphore来解决这个问题. 首先也来看看如何使用信号量,信号量Semaphore常用有三个函数,使用很方便.下面是这几个函数的原型和使

linux网络编程-----&gt;线程同步--&gt;信号量

开发使用多线程过程中, 不可避免的会出现多个线程同时操作同一块共享资源, 当操作全部为读时, 不会出现未知结果, 一旦当某个线程操作中有写操作时, 就会出现数据不同步的事件. 而出现数据混乱的原因: 资源共享(独享资源则不会) 调试随机(对数据的访问会出现竞争) 线程间缺少必要的同步机制 以上三点, 前两点不能被改变. 欲提高效率, 传递数据, 资源必须共享. 只要资源共享, 就一定会出现线程间资源竞争, 只要存在竞争关系, 数据就会出现混乱. 所以只能从第三点着手, 使多个线程在访问共享资源的

秒杀多线程第八篇 经典线程同步 信号量Semaphore (续)

java semaphore实现: Semaphore当前在多线程环境下被扩放使用,操作系统的信号量是个很重要的概念,在进程控制方面都有应用.Java 并发库 的Semaphore 可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可.比如在Windows下可以设置共享文件的最大客户端访问个数. package com.multithread.semaphore; import

秒杀多线程第九篇 经典线程同步总结 关键段 事件 互斥量 信号量

版权声明:本文为博主原创文章,未经博主允许不得转载. 前面<秒杀多线程第四篇一个经典的多线程同步问题>提出了一个经典的多线程同步互斥问题,这个问题包括了主线程与子线程的同步,子线程间的互斥,是一道非常经典的多线程同步互斥问题范例,后面分别用了四篇 <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event> <秒杀多线程第七篇经典线程同步互斥量Mutex> <秒杀多线程第八篇经典线程同步信号量Semaphore> 来