【操作系统】同步和互斥详细讲解(算法+源码)

本文详细介绍了操作系统中的同步与互斥概念,通过C语言示例展示了如何在多线程环境下使用互斥锁保护共享资源。文章还探讨了同步在各种场景下的应用,如线程协调、异步编程、GUI和网络通信,以及互斥在共享资源保护、数据库访问等方面的作用。
摘要由CSDN通过智能技术生成

博主介绍:✌全网粉丝喜爱+、前后端领域优质创作者、本质互联网精神、坚持优质作品共享、掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战✌有需要可以联系作者我哦!

🍅附上相关C语言版源码讲解🍅

👇🏻 精彩专栏推荐订阅👇🏻 不然下次找不到哟

一、同步与互斥概念

操作系统中的同步和互斥操作是指处理多个任务或进程时的不同方式。多个线程访问共享数据时,使用互斥锁可以确保在任意时刻只有一个线程能够修改数据,防止数据不一致。

同步定义: 同步是指多个任务或进程按照一定的顺序执行,以确保它们之间的关系和协调。

关键点:

  1. 协调执行: 任务按照一定的规则或条件顺序执行,以避免不确定的结果。
  2. 等待机制: 在同步环境中,一个任务的执行可能需要等待其他任务的完成或满足特定条件。

互斥定义: 互斥是指在同一时刻只允许一个任务或进程访问共享资源,以防止数据竞争和一致性问题。

关键点:

  1. 独占资源: 一次只有一个任务能够访问临界区(共享资源的代码段)。
  2. 互斥锁: 通常使用互斥锁等机制来保护共享资源,确保只有一个任务能够持有锁并访问资源。

二、算法

#include <windows.h>
#include <iostream>
#include<stdio.h>

bool g_continue = true; //控制程序结束
HANDLE g_hS; //当盘子为空时的线程 
HANDLE g_hS0; //当盘子中放的是桔子线程 
HANDLE g_hS1; //当盘子中放的是苹果线程 
DWORD WINAPI father(LPVOID); //定义父亲线程
DWORD WINAPI son(LPVOID); //定义儿子线程
DWORD WINAPI daughter(LPVOID);//定义女儿线程
int main()  
{  
 //创建各个互斥与资源信号量  
 g_hS = CreateSemaphore(NULL,1,1,NULL);  //盘子中是否有水果 
 g_hS0 = CreateSemaphore(NULL,0,1,NULL);  //盘子中的水果为桔子 
 g_hS1 = CreateSemaphore(NULL,0,1,NULL);  //盘子中的水果为苹果 

//其中第2和3个参数为信号量的初始值和最大值

 const unsigned short father_COUNT = 0; //声明父亲
 const unsigned short son_COUNT = 0; //声明儿子
 const unsigned short daughter_COUNT = 0;//声明女儿
 
 //总的线程数 
 const unsigned short THREADS_COUNT = father_COUNT+son_COUNT+daughter_COUNT ;  
 HANDLE hThreads[THREADS_COUNT]; //各线程的handle  
 DWORD fatherID[father_COUNT]; //父亲线程的标识符
 DWORD sonID[son_COUNT]; //儿子线程的标识符  
 DWORD daughterID[daughter_COUNT]; //女儿线程的标识符
 
//创建父亲进程

 hThreads[0]=CreateThread(NULL,0,father,NULL,0,&fatherID[0]);  
  if (hThreads[0]==NULL) return -1;  
 
//创建儿子进程
  
 hThreads[1]=CreateThread(NULL,0,son,NULL,0,&sonID[0]);  
  if (hThreads[1]==NULL) return -1;  
 
//创建女儿进程
 
 hThreads[2]=CreateThread(NULL,0,daughter,NULL,0,&daughterID[0]);  
  if (hThreads[2]==NULL) return -1;  


 while(g_continue){  
  if(getchar()){ //按回车后终止程序运行  
	  g_continue = false;  
  }  
 }  

 return 0;  
}  
//父亲放水果的操作,输出  

void eat()  
{  
 std::cerr << "儿子吃桔子" << std::endl;  
}  

 
void eat1()  
{  
 std::cerr << "女儿吃苹果" << std::endl;  
}  

//父亲进程  
DWORD WINAPI father(LPVOID lpPara)  
{  
 while(g_continue){  
  WaitForSingleObject(g_hS,INFINITE);   
  
  int juzhi=rand()%2; //设置了一个随机数,来模拟父亲放的是什么水果 
  Sleep(1500);//方便观察实验结果
  if(juzhi==1){
  	  printf("父亲放入了一个桔子\n");
  	  Sleep(1000);
      ReleaseSemaphore(g_hS0,1,NULL); 
  }
  else{
  	printf("父亲放入了一个苹果\n"); 
  	Sleep(1000);
	   ReleaseSemaphore(g_hS1,1,NULL); 
 }
 }  
 return 0;  
}  

//儿子进程 
DWORD WINAPI son(LPVOID lpPara)  
{  
 while(g_continue){  
  WaitForSingleObject(g_hS0,INFINITE); 
   eat(); 
   Sleep(1500); 
  ReleaseSemaphore(g_hS,1,NULL);   
 }  
 return 0;  
}    

//女儿进程 
DWORD WINAPI daughter(LPVOID lpPara)  
{  
 while(g_continue){  
  WaitForSingleObject(g_hS1,INFINITE);    
  eat1(); 
  Sleep(1500); 
  ReleaseSemaphore(g_hS,1,NULL); 
 }  
 return 0;  
}    

执行结果

三、总结

同步的应用:

  1. 线程同步: 在多线程编程中,同步用于协调多个线程的执行,确保它们按照一定的顺序执行或等待某些条件满足后再继续执行。

  2. 协同任务: 同步可以用于协同任务的执行,确保任务之间的依赖关系和顺序。

  3. 异步编程: 同步机制常用于异步编程中,确保异步任务的正确执行顺序。

  4. GUI应用: 在图形用户界面(GUI)应用中,同步用于处理用户界面的响应和更新,以保持用户体验。

  5. 网络通信: 同步操作常用于等待网络数据的到达或发送数据后等待确认。

互斥的应用:

  1. 共享资源保护: 互斥机制用于保护共享资源,防止多个线程或进程同时访问导致数据不一致性或竞态条件。

  2. 临界区保护: 互斥锁用于保护临界区,确保在任意时刻只有一个线程能够执行临界区的代码。

  3. 文件操作: 互斥可以用于文件读写操作,以确保在写操作进行时不会发生读操作,反之亦然。

  4. 数据库访问: 在数据库应用中,互斥用于保护对数据库的访问,以防止并发访问导致数据不一致。

  5. 资源分配: 互斥可以用于保护对有限资源的访问,如线程池中的线程对任务的分配。

综合应用:

  1. 生产者-消费者问题: 使用同步和互斥来解决生产者和消费者之间的数据共享和协调问题。

  2. 读写锁: 读写锁结合了同步和互斥的特性,允许多个线程同时读取共享数据,但在写操作时进行互斥。

  3. 定时任务调度: 同步和互斥可以用于定时任务的调度,确保任务在指定时间执行。

  4. 并行计算: 在并行计算中,同步和互斥用于协调和保护多个计算单元的执行。

大家点赞、收藏、关注、评论啦 !

谢谢哦!如果不懂,欢迎大家下方讨论学习哦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序小勇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值