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

2021/11/28 7:13:03

本文主要是介绍【Linux】线程安全——线程同步(信号量),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

      • (一)问题描述
        • (1)未同步(异步)多线程代码
      • (二)信号量控制线程同步
        • (1)同步多线程代码

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


(一)问题描述

创建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;
}
  • 结果:在多次实验下,使用信号量保证了线程安全
    在这里插入图片描述


这篇关于【Linux】线程安全——线程同步(信号量)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程