linux高级编程之进程线程(西红柿种子.十)---线程同步

        本文主要分享的是信号量的函数接口,信号量较之锁而言能够实现线程间的同步,因此使用极为广泛,能够使得我们有序的使用资源,以此来实现对资源的分配;
        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;
}

希望大家能够认真分析两个代码的对比,理解锁和信号量各自的优缺点;欢迎评论区留言哦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值