本文主要分享的是信号量的函数接口,信号量较之锁而言能够实现线程间的同步,因此使用极为广泛,能够使得我们有序的使用资源,以此来实现对资源的分配;
1.信号量:
是一种资源(有限),可以被申请和释放
申请资源:资源数-1,如果资源数为0,则等待释放资源后,才能得到资源
释放资源:资源数+1
信号量只能被申请、释放、初始化、销毁四种操作
(1)sem_init
int sem_init(sem_t *sem, int pshared, unsigned int value);
功能:
初始化信号量
参数:
sem:信号量空间首地址
pshared:
0 进程的多个线程间共享
非0 进程间共享
value:
信号量的值
返回值:
成功返回0
失败返回-1
(2)sem_destroy
int sem_destroy(sem_t *sem);
功能:
信号量的销毁
参数:
sem:信号量空间首地址
返回值:
成功返回0
失败返回-1
(3)sem_wait
int sem_wait(sem_t *sem);
功能:
申请信号量(信号量资源数-1),如果资源数为0,则阻塞等待直到
获得资源才能继续向下执行
参数:
sem:信号量空间首地址
返回值:
成功返回0
失败返回-1
(4)sem_post
int sem_post(sem_t *sem);
功能:
释放信号量(信号量资源数+1),不阻塞
参数:
sem:信号量空间首地址
返回值:
成功返回0
失败返回-1
2.产生随机数的方法:
srand(time(NULL));根据一个数(1900年到现在的秒数)产生一组随机数列;
rand();第一次调用取随即数列中的第一个值,所以取到的值是不变的;第二次调用取随即数列中的第二个值,以此类推;
3.用锁和信号量分别实现以下功能:
有三台ATM机,有10个人需要到ATM取钱,ATM机中只允许一个人进入,
请打印出10个人进入ATM中的顺序,及其过程。
(1)使用锁完成
int atm = 3;
10个线程
进入ATM:
prinitf("TID:XXX 进入ATM机\n");
取钱:
sleep(随机值);
出ATM:
printf("TID:XXX 离开ATM机\n");
先了解下头文件:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
主函数如下,第一步一定是先了解程序框架,不论他多么简单:
int main(int argc, const char *argv[])
{
pthread_t tid[10];
int i = 0;
int a[10] = {1,2,3,4,5,6,7,8,9,10}; //定义每个线程的标号,由于每个线程的循环中可能同时会读取i的值,所以不传i,单独定义线程标号
pthread_mutex_init(&lock, NULL); //初始化锁
for(i = 0; i < 10;++i)
{
pthread_create(&tid[i], NULL, thread, &a[i]); //循环创建线程
}
for(i = 0;i < 10;++i)
{
pthread_join(tid[i], NULL); //循环回收现成
}
return 0;
}
最后呢来看一下线程任务(10个线程做的事情相同)
int atm = 3; //定义资源个数,总共三个ATM机
pthread_mutex_t lock; //定义锁
void *thread(void *arg)
{
int sec;
while (1)
{
pthread_mutex_lock(&lock); //上锁,占用资源
if (atm > 0)
{
atm--;
pthread_mutex_unlock(&lock);
break; //退出开始实现业务逻辑
}
else
{
pthread_mutex_unlock(&lock); //如果此时没有资源,那么直接解锁继续循环检测是否有锁
}
}
printf("%d:线程TID:%#x进入ATM机...\n", *(int *)arg, (unsigned int)pthread_self());
srand(time(NULL));
sec = rand() % 10 + 1;
sleep(sec);
printf("%d:线程TID:%#xATM机...\n", *(int *)arg, (unsigned int)pthread_self());
pthread_mutex_lock(&lock);
atm++;
pthread_mutex_unlock(&lock);
}
执行结果如下:
由于线程的任务调度不同,所以每次的运行结果都是不同的;
这个就是使用锁实现ATM机的简单功能;下面来看一下使用信号量的操作:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include <semaphore.h>
sem_t atm; //信号量定义
void *thread(void *arg)
{
sem_wait(&atm); //阻塞等待申请资源
printf("%d(TID:%#x)进来了\n", *(int *)arg, (unsigned int)pthread_self());
sleep(rand() % 10 + 1);
printf("%d(TID:%#x)出去了\n", *(int *)arg, (unsigned int)pthread_self());
sem_post(&atm); //释放资源
}
int main(int argc, const char *argv[])
{
pthread_t tid[10];
int i = 0;
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
srand(time(NULL));
sem_init(&atm, 0, 3); //信号量初始化
for(i = 0;i < 10;++i)
{
pthread_create(&tid[i], NULL, thread, &a[i]);
}
for(i = 0;i < 10;++i)
{
pthread_join(tid[i], NULL);
}
sem_destroy(&atm); //释放信号量空间
return 0;
}
希望大家能够认真分析两个代码的对比,理解锁和信号量各自的优缺点;欢迎评论区留言哦!