目录
信号量介绍
信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。
当公共资源增加时,调用函数sem_post()
增加信号量。只有当信号量值大于0
时,才能使用公共资源,使用后,函数sem_wait()
减少信号量。函数sem_trywait()
和函数pthread_ mutex_trylock()
起同样的作用,它是函数sem_wait()
的非阻塞版本。下面我们逐个介绍和信号量有关的一些函数,它们都在头文件/usr/include/semaphore.h
中定义。
信号量的数据类型为结构sem_t
,它本质上是一个长整型的数。
函数sem_init()
用来初始化一个信号量。它的原型为:
int sem_init(sem_t *sem, int pshared, unsigned int value);
sem
为指向信号量结构的一个指针;pshared
不为0
时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value
给出了信号量的初始值。
函数sem_post(sem_t *sem)
用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。
函数sem_wait(sem_t *sem)
被用来阻塞当前线程直到信号量sem
的值大于0
,解除阻塞后将sem
的值减一,表明公共资源经使用后减少。
函数sem_trywait (sem_t *sem)
是函数sem_wait()
的非阻塞版本,它直接将信号量sem
的值减一。
函数sem_destroy(sem_t *sem)
用来释放信号量sem
。
例子: 利用信号量机制控制多线程的运行顺序,分析多线程中数据的共享情况;
程序源代码
1 |
/* File sem.c */ |
信号量控制多线程的运行顺序的原理很简单,有多少个线程就设置多少个信号量,首先执行的信号量初始值为1
,其他信号量初始值为0
,所以就算其他线程先占有CPU但也会被阻塞在sem_wait()
函数那里,只有信号量为1
的那个线程执行完后然后增加下一个信号量的值,下一个信号量对应的线程才能执行,其他线程就算得到CPU也无法执行,然后最后一个线程增加第一个线程的信号量就可以组成一个环,这样子就可以实现多线程之间的顺序执行。
编译运行
1 |
hylee@ubuntu:~/Desktop$ gcc sem.c -lpthread -o sem |
可以看到主线程和子线程共享全局变量i,当某个线程改变了i的值时,另外一个线程读取是也会读取到修改后的值,即进程中的多个线程共享进程的数据。
Linux系统下多进程与多线程中的区别(通过实验现象可以看出来的):
如果使用的是fork函数实现多进程的编程,对于全局变量i,如果某个进程对i进行了修改,并不会影响另外一个进程i的值(写时复制)。
程序代码:
1 |
#include<stdio.h> |
编译运行:
1 |
hylee@ubuntu:~/Desktop$ gcc fork.c -o fork |
可以看到父进程对i进行修改对子进程中的i没有任何影响,反之也一样。
留言