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

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

??附上相关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("父亲放入了一个桔子
");
  	  Sleep(1000);
      ReleaseSemaphore(g_hS0,1,NULL); 
  }
  else{
  	printf("父亲放入了一个苹果
"); 
  	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. 并行计算: 在并行计算中,同步和互斥用于协调和保护多个计算单元的执行。

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

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