linux多线程----信号量
来源:互联网 发布:云海软件 编辑:程序博客网 时间:2024/05/23 19:14
信号量:信号量是操作系统中所用到的PV原子操作,他广泛用于进程与线程的同步与互斥,信号量本质是一个非负的整数计数器,被用来控制对公共资源的访问,下面是pv操作的工作原理:
PV原子操作是对整数计数器信号量sem的操作,一次p操作使sem减1,一次v操作使sem加1,进程或者线程根据信号量判断是否对公共资源具有访问权限,当信号量sem的值大于等于0时,则进程或线程具有公共资源的访问权,当信号量小于0时,则进程或线程会被阻塞,直到信号量sem大于等于0为止
信号值的含义:
如果信号量的值大于0表示可用的资源数,小于0表示阻塞的进程数
p操作:
将信号量减一后,如果>=0,则表示有可用的资源,线程继续执行
信号量减一后,如果<0,则线程会被阻塞,放在阻塞队列中
v操作:
将信号量加一后,如果大于0表示没有阻塞的线程
将信号量加一后,如果小于0或者等于0,说明之前s<0表示有线程在等待队列中,从等待队列中取出一个线程执行。
pv操作必须成对的使用
pv操作主要用于进程或线程的同步和互斥两种情况,如果用于互斥,只需设置一个信号量sem,其流程图如下:
当信号量用于同步操作时,通常需要设置多个信号量,并安排不同的初始值来实现他们的之间的执行顺序,其流程如下:
linux实现了POSIX的无名信号量,主要用于线程间的互斥与同步,这里主要介绍了几个函数:
- sem_init()用于创建一个信号量,并初始化他的值
- sem_wait()和sem_trywait()都相当于P操作,当信号量大于0时他们都会将信号量减一,两者的区别是当信号量小于0时,sem_wait()会阻塞进程,而sem_trywait()会立即返回
- sem_post()相当于V操作,他将信号量的值加1同时发出信号来唤醒等待的进程
- sem_getvalue()用于得到信号量的值
- sem_destroy()用于删除信号量
sem_init()函数格式如下:
sem_wait()函数语法如下:
下面这个例子通过信号量实现三个线程有序的执行,按照创创建的相反顺序执行:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define THREAD_NUMBER 3//线程个数
#define REPEAT_NUMBER 3
#define DELAY_TIME_LEVELS 10.0
void *thrd_func(void *arg)//线程函数
{
int thrd_num = (int)arg ;
int delay_time = 0 ;
int count = 0 ;
sem_wait(&sem[thrd_num]) ;//执行P操作,信号量的值减一
printf("thread %d is starting\n", thrd_num) ;
for (count = 0; count < REPEAT_NUMBER; count++)//每个线程完成五次任务
{
delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;//产生随机时间
sleep(delay_time) ;
printf("\tThread %d:job %d delay = %d\n",
thrd_num, count, delay_time) ;
}
printf("thread %d finished\n", thrd_num) ;
pthread_exit(NULL) ;
}
int main()
{
pthread_t thread[THREAD_NUMBER] ;
int no = 0, res ;
void *thrd_ret ;
srand(time(NULL)) ;//产生随机种子
pthread_mutex_init(&mutex, NULL ) ;//初始化互斥锁,默认的是快速互斥锁
for(no = 0; no < THREAD_NUMBER; no++)
{
sem_init(&sem[no], 0, 0) ;//初始化信号量,将其值设为0
res = pthread_create(&thread[no], NULL, thrd_func, (void *)no) ;//创建线程
if (res != 0)
{
printf("create thread %d failed\n", no) ;
exit(res) ;
}
}
printf("create threads success\n waiting for threads to finish...\n") ;
sem_post(&sem[THREAD_NUMBER - 1]) ;//对最后一个信号量执行V操作
for (no = THREAD_NUMBER - 1; no >= 0; no--)
{
res = pthread_join(thread[no], &thrd_ret) ;
if (!res)
{
printf("thread %d joined\n", no) ;
}
else
{
printf("thread %d joined failed", no) ;
}
sem_post(&sem[(no + THREAD_NUMBER - 1) % THREAD_NUMBER]) ;//对相应的信号量执行V操作
}
for (no = 0; no < THREAD_NUMBER; no++)
{
sem_destroy(&sem[no]) ;//销毁信号量
}
exit(0) ;
}
#include <stdlib.h>
#include <pthread.h>
#define THREAD_NUMBER 3//线程个数
#define REPEAT_NUMBER 3
#define DELAY_TIME_LEVELS 10.0
void *thrd_func(void *arg)//线程函数
{
int thrd_num = (int)arg ;
int delay_time = 0 ;
int count = 0 ;
sem_wait(&sem[thrd_num]) ;//执行P操作,信号量的值减一
printf("thread %d is starting\n", thrd_num) ;
for (count = 0; count < REPEAT_NUMBER; count++)//每个线程完成五次任务
{
delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;//产生随机时间
sleep(delay_time) ;
printf("\tThread %d:job %d delay = %d\n",
thrd_num, count, delay_time) ;
}
printf("thread %d finished\n", thrd_num) ;
pthread_exit(NULL) ;
}
int main()
{
pthread_t thread[THREAD_NUMBER] ;
int no = 0, res ;
void *thrd_ret ;
srand(time(NULL)) ;//产生随机种子
pthread_mutex_init(&mutex, NULL ) ;//初始化互斥锁,默认的是快速互斥锁
for(no = 0; no < THREAD_NUMBER; no++)
{
sem_init(&sem[no], 0, 0) ;//初始化信号量,将其值设为0
res = pthread_create(&thread[no], NULL, thrd_func, (void *)no) ;//创建线程
if (res != 0)
{
printf("create thread %d failed\n", no) ;
exit(res) ;
}
}
printf("create threads success\n waiting for threads to finish...\n") ;
sem_post(&sem[THREAD_NUMBER - 1]) ;//对最后一个信号量执行V操作
for (no = THREAD_NUMBER - 1; no >= 0; no--)
{
res = pthread_join(thread[no], &thrd_ret) ;
if (!res)
{
printf("thread %d joined\n", no) ;
}
else
{
printf("thread %d joined failed", no) ;
}
sem_post(&sem[(no + THREAD_NUMBER - 1) % THREAD_NUMBER]) ;//对相应的信号量执行V操作
}
for (no = 0; no < THREAD_NUMBER; no++)
{
sem_destroy(&sem[no]) ;//销毁信号量
}
exit(0) ;
}
其原理就是利用pv操作来进行线程的控制,首先三个线程都被阻塞住了,然后对第三个信号量执行V操作,依次向上,这样线程就从创建的反方向执行了,其结果如下:
可以明显看出信号量控制了线程的执行顺序。
0 0
- linux多线程----信号量
- linux多线程----信号量
- linux多线程 --信号量
- Linux多线程编程-信号量
- Linux 多线程同步(信号量)
- Linux 多线程同步(信号量)
- linux 多线程用信号量进行同步例子
- linux程序设计 线程 多线程编程 信号量
- Linux编程练习 --多线程5--信号量(semaphore)
- linux 多线程编程 ---- 信号量的使用
- linux多线程编程5--信号量(semaphore)
- 【Linux】 多线程编程(信号量实现同步)
- Linux编程练习 --多线程5--信号量(semaphore)
- linux 多线程编程---- 信号量的使用
- linux多线程编程5--信号量(semaphore)
- Linux编程练习 --多线程5--信号量(semaphore)
- linux多线程编程5--信号量(semaphore)
- linux下多线程编程,各种锁,信号量
- 键盘自定义
- 如何在eclipse jee中创建Maven project并且转换为Dynamic web project
- Makefile学习
- 近几年微软笔试题汇总分类解析
- mybatis入门到精通(九):mybatis 代码生成工具的使用
- linux多线程----信号量
- python写算法之快速排序
- java多线程总结
- Android 常用 uri
- 虚拟化系列-VMware vSphere 5.1 简介与安装
- 这种是VMP壳吗?
- NGUI系列教程一
- 如何在eclipse jee中检出项目并转换为Maven project,最后转换为Dynamic web project
- wince c# 程序只能运行一次