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

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

一、同步与互斥概念

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

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

关键点:

  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. 并行计算: 在并行计算中,同步和互斥用于协调和保护多个计算单元的执行。

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

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


相关文章
|
2月前
|
算法 调度 UED
探索操作系统的心脏:调度算法的奥秘与影响
【10月更文挑战第9天】 本文深入探讨了操作系统中至关重要的组件——调度算法,它如同人体的心脏,维持着系统资源的有序流动和任务的高效执行。我们将揭开调度算法的神秘面纱,从基本概念到实际应用,全面剖析其在操作系统中的核心地位,以及如何通过优化调度算法来提升系统性能。
|
1月前
|
算法 调度 Python
深入理解操作系统中的进程调度算法
在操作系统中,进程调度是核心任务之一,它决定了哪个进程将获得CPU的使用权。本文通过浅显易懂的语言和生动的比喻,带领读者了解进程调度算法的重要性及其工作原理,同时提供代码示例帮助理解。
|
9天前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
38 3
|
1月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
128 7
|
1月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
106 8
|
1月前
|
算法 大数据 Linux
深入理解操作系统之进程调度算法
【10月更文挑战第24天】本文旨在通过浅显易懂的语言,带领读者深入了解操作系统中的进程调度算法。我们将从进程的基本概念出发,逐步解析进程调度的目的、重要性以及常见的几种调度算法。文章将通过比喻和实例,使复杂的技术内容变得生动有趣,帮助读者建立对操作系统进程调度机制的清晰认识。最后,我们还将探讨这些调度算法在现代操作系统中的应用和发展趋势。
|
2月前
|
算法 调度 UED
深入理解操作系统的进程调度算法
【10月更文挑战第7天】在操作系统的心脏——内核中,进程调度算法扮演着至关重要的角色。它不仅影响系统的性能和用户体验,还直接关系到资源的合理分配。本文将通过浅显易懂的语言和生动的比喻,带你一探进程调度的秘密花园,从最简单的先来先服务到复杂的多级反馈队列,我们将一起见证算法如何在微观世界里编织宏观世界的和谐乐章。
|
2月前
|
边缘计算 算法 调度
探究操作系统的心脏:调度算法的进化与影响
【10月更文挑战第2天】 本文深入探讨了操作系统中核心组件——调度算法的历史演变、关键技术突破及其对现代计算的影响。通过详细回顾从单任务到多任务、实时系统及分布式计算环境下调度算法的发展,文章揭示了这些算法如何塑造我们的数字世界,并对未来的趋势进行了展望。不同于传统的摘要,本文特别聚焦于技术细节与实际应用的结合点,为读者提供一幅清晰的技术演进蓝图。
70 4
|
2月前
|
算法 调度 UED
探索操作系统的心脏:进程调度算法
【9月更文挑战第32天】在数字世界的每一次心跳中,都隐藏着一个不为人知的英雄——进程调度算法。它默默地在后台运作,确保我们的命令得到快速响应,应用程序平稳运行。本文将带你走进操作系统的核心,一探进程调度的奥秘,并通过代码示例揭示其背后的智慧。准备好跟随我一起深入这趟技术之旅了吗?让我们开始吧!
|
3月前
|
算法 调度
操作系统的心脏:深入解析进程调度算法
本文旨在深入探讨现代操作系统中的核心功能之一——进程调度。进程调度算法是操作系统用于分配CPU时间片给各个进程的机制,以确保系统资源的高效利用和公平分配。本文将详细介绍几种主要的进程调度算法,包括先来先服务(FCFS)、短作业优先(SJF)、时间片轮转(RR)以及优先级调度(PS)。我们将分析每种算法的基本原理、优缺点及其适用场景。同时,本文还将讨论多级反馈队列(MFQ)调度算法,并探讨这些算法在实际应用中的表现及未来发展趋势。通过深入解析这些内容,希望能够为读者提供对操作系统进程调度机制的全面理解。

热门文章

最新文章