您的位置:首页 > 运维架构 > Linux

信号量进行同步(linux POSIX的实时扩展,用于线程)!

2015-08-27 15:38 537 查看
信号量提出背景:

程序中2线程共享全局变量时(一个是main函数顺序“线程”,一个是create线程),会导致“忙等待”时,线程之间

来回切换,非常笨拙且没有效率,由此荷兰计算机科学家Dijkstra提出了信号量的概念;

对信号量的一般特点

1. 有2组,一组是posix的实时扩展,用于线程(本博的主要内容);另外一组为系统V信号量,用于进程同步;

2. 信号量是特殊的变量,可以被增加和减少,一般用最简单的信号量--二进制,另外一种是计数信号量,不在此讨论;

计数信号量不常用;

相关函数

线程中使用的基本信号量函数有4个,

1.头文件:#include <semaphore.h>

2.原型:

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

pshared 参数控制信号量的类型,为0,:表示这个信号量是当前的进程的局部信号量,否则,这个信号量可以在多个进程之间

共享;(该博只对不能在进程间共享的信号量感兴趣);

int sem_post(sem_t *sem);

int sem_wait(sem_t *sem);

1. sem_post 函数的作用是以原子操作的方式给信号量的值加1.(原子操作:P424有说明);

2. sem_wait函数以原子操作的方式将信号量的值减1,它会等待直到信号量有个非零值才会开始减操作,为0就等待;

3. 如果有2个wait等待信号量为非零值,只有一个等待线程开始对信号量减1,另外一个线程继续等待;

int sem_destroy(sem_t *sem);

与大多数linux函数一样,成功返回0。

例子:

root@ubuntu:/mnt/hgfs/D/linux_program/ch12# cat -n thread3.c
1	#include <stdio.h>
2	#include <unistd.h>
3	#include <stdlib.h>
4	#include <string.h>
5	#include <pthread.h>
6	#include <semaphore.h>
7
8	void *thread_function(void *arg);
9	sem_t bin_sem;
10
11	#define WORK_SIZE 1024
12	char work_area[WORK_SIZE];
13
14	int main() {
15	    int res;
16	    pthread_t a_thread;
17	    void *thread_result;
18
19	    res = sem_init(&bin_sem, 0, 0);
20	    if (res) {
21	        perror("Semaphore initialization failed");
22	        exit(EXIT_FAILURE);
23	    }
24	    res = pthread_create(&a_thread, NULL, thread_function, NULL);
25	    if (res) {
26	        perror("Thread creation failed");
27	        exit(EXIT_FAILURE);
28	    }
29	    printf("Input some text. Enter 'end' to finish\n");
30	    while(memcmp("end", work_area, 3) != 0) {
31	        fgets(work_area, WORK_SIZE, stdin);
32	        sem_post(&bin_sem);
33	    }
34	    printf("\nWaiting for thread to finish...\n");
35	    res = pthread_join(a_thread, &thread_result);
36	    if (res) {
37	        perror("Thread join failed");
38	        exit(EXIT_FAILURE);
39	    }
40	    printf("Thread joined\n");
41	    sem_destroy(&bin_sem);
42	    exit(EXIT_SUCCESS);
43	}
44
45	void *thread_function(void *arg) {
46		sem_wait(&bin_sem);
47	    while(memcmp("end", work_area, 3) != 0) {
48	        printf("You input %d characters\n", strlen(work_area)-1);
49	   		sem_wait(&bin_sem);
50		 }
51	    pthread_exit(NULL);
52	}
root@ubuntu:/mnt/hgfs/D/linux_program/ch12# ./thread3
Input some text. Enter 'end' to finish
end

Waiting for thread to finish...
Thread joined
root@ubuntu:/mnt/hgfs/D/linux_program/ch12# ./thread3
Input some text. Enter 'end' to finish
hello world
You input 11 characters
endget

Waiting for thread to finish...
Thread joined
root@ubuntu:/mnt/hgfs/D/linux_program/ch12#


去掉thread_function函数体内的第一个sem_wait(&bin_sem)会出现什么现象,删除第二个呢?初始设信号量为1又是怎么打印呢?

删除第一个的打印情况:

root@ubuntu:/mnt/hgfs/D/linux_program/ch12# ./thread3
Input some text. Enter 'end' to finish
You input -1 characters
clear
You input 5 characters
end

Waiting for thread to finish...
Thread joined
root@ubuntu:/mnt/hgfs/D/linux_program/ch12#


删除第二个sem_wait(&bin_sem)打印情况如下:(死循环)

root@ubuntu:/mnt/hgfs/D/linux_program/ch12# gcc -D_REENTRANT -o thread3 thread3.c -lpthread
root@ubuntu:/mnt/hgfs/D/linux_program/ch12# ./thread3
Input some text. Enter 'end' to finish
hello csdn
You input 10 characters
You input 10 characters
You input 10 characters
You input 10 characters
You input 10 characters
You input 10 characters
You input 10 characters
You input 10 characters
You input 10 characters
You input 10 characters
You input 10 characters
You input 10 characters
You input 10 characters
You input 10 characters
You input 10 characters
^[^AYou input 10 characters
You input 10 characters
You input 10 characters
You input 10 characters
^C
root@ubuntu:/mnt/hgfs/D/linux_program/ch12#


初始设信号量为1又是怎么打印:

root@ubuntu:/mnt/hgfs/D/linux_program/ch12# ./thread3
Input some text. Enter 'end' to finish
You input -1 characters
clear
You input 5 characters
c
You input 1 characters
hello csdn
You input 10 characters
end

Waiting for thread to finish...
Thread joined
root@ubuntu:/mnt/hgfs/D/linux_program/ch12#
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: