ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

【Linux】线程安全——线程同步(信号量)

2021-11-27 19:58:11  阅读:193  来源: 互联网

标签:int void 信号量 ++ 线程 Linux sem include


文章目录


我们简单写个多个线程并发对一个全局变量进行++操作


(一)问题描述

创建5个线程,一个全局变量gdata = 0; 让每个线程都对gdata进行++100次,理想结果就是499

(1)未同步(异步)多线程代码

  • 代码
#include <stdio.h>
#include <string.h>
#include <pthread.h>

int gdata = 0;

void* pthread_fun(void* arg)
{
	for(int i = 0; i < 100; i++)
	{
		printf("gdata_after = %d\n", gdata++);
	}
}

int main()
{
	pthread_t id[5];
	//创建5个线程
	for(int i = 0; i < 5; i++)
	{
		pthread_create(&id[i], NULL, pthread_fun, NULL);
	}

	//等待五个进程结束
	for(int i = 0; i < 5; i++)
	{
		pthread_join(id[i], NULL);
	}
	return 0;
}
  • 结果:可以看到gdata时而499,时而498,很明显程序有问题!!
    在这里插入图片描述

(二)信号量控制线程同步

思路:使用一个信号量加以控制,即可,因为不在乎是那个线程先运行,所以只要保证再gdata++的时候,让其他的线程阻塞就好了,这样就能保证最后的结果== 499

(1)同步多线程代码

代码:

  • sem.h
#include <stdio.h>
#include <unistd.h>
#include <sys/sem.h>

union semun
{
	int val;
};

void sem_init();

void sem_p();

void sem_v();

void sem_destory();
  • sem.c
#include "sem.h"

//信号量集的id
static int semid = -1;

void sem_init()
{
	//创建
	semid = semget((key_t)8888, 1, IPC_CREAT | IPC_EXCL | 0600);
	if(semid == -1)
	{
		semid = semget((key_t)8888, 0, IPC_CREAT);
		if(semid == -1)
		{
			perror("semget err");
			return;
		}
	}
	//初始化
	else
	{
		//定义1个信号量
		union semun sem_val;
		sem_val.val = 1;
		
		if(semctl(semid, 0, SETVAL, sem_val) == -1)
		{
			perror("sem_val init err");
			return;
		}

	}
}

void sem_p()
{
	struct sembuf buf;
	buf.sem_num = 0;
	buf.sem_op = -1;
	buf.sem_flg = SEM_UNDO;

	if(semop(semid, &buf, 1) == -1)
	{
		printf("sem_p err\n");
		return;
	}

}

void sem_v(int index)
{
	struct sembuf buf;
	buf.sem_num = 0;
	buf.sem_op = 1;
	buf.sem_flg = SEM_UNDO;

	if(semop(semid, &buf, 1) == -1)
	{
		printf("sem_v err\n");
		return;
	}
}

void sem_destory()
{
	if(semctl(semid, 0, IPC_RMID) == -1)
	{
		perror("sem_destory err");
		return;
	}
}
  • new.c
#include "sem.h"
#include <pthread.h>
#include <unistd.h>
int gdata = 0;

void* pthread_fun(void* arg)
{
	int* index = (int*)arg;
	
	sem_p(*index);

	for(int i = 0; i < 100; i++)
	{
		printf("gdata_after = %d\n", gdata++);
	}
	sem_v(*index);

}

int main()
{
	//初始化信号量集
	sem_init();

	pthread_t id[5];
	//创建5个线程
	for(int i = 0; i < 5; i++)
	{
		pthread_create(&id[i], NULL, pthread_fun, &i);
	}

	//等待五个进程结束
	for(int i = 0; i < 5; i++)
	{
		pthread_join(id[i], NULL);
	}

	//销毁信号量集
	sem_destory();
	return 0;
}
  • 结果:在多次实验下,使用信号量保证了线程安全
    在这里插入图片描述

标签:int,void,信号量,++,线程,Linux,sem,include
来源: https://blog.csdn.net/xiaoxiaoguailou/article/details/121580048

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有