精华内容
下载资源
问答
  • 进程同步是指对多个相关进程在执行次序上进行协调,以使并发...用之前一直处于睡眠状态,这样就使子进程先运行,子进程运行exec()装入命令后,然后调用wait(0),使子进程和父进程并发执行,实现进程同步。 转载于...

     

    进程同步是指对多个相关进程在执行次序上进行协调,以使并发执行的主进程之间有

    效地共享资源和相互合作,从而使程序的执行具有可在现行。

    首先,程序在调用fork()机那里了一个子进程后,马上调用wait(),使父进程在子进程调

    用之前一直处于睡眠状态,这样就使子进程先运行,子进程运行exec()装入命令后,然后调用wait(0),使子进程和父进程并发执行,实现进程同步。

    转载于:https://www.cnblogs.com/kazama/p/10734962.html

    展开全文
  • 线程与进程的关系3.定义:区别:如上!!!4.wait()和sleep()5.线程的状态及其他API二、线程锁线程并发同步时,引入了锁机制。1. 普通锁机制:synchronized 修饰代码块与volatile 修饰成员变量2.Lock!!共同点:都...

    前文:

    单线程——多线程的开启——线程锁——线程同步工具——手写连接池——连接池工具类。

    一、线程

    1.线程的概念

    e5b20445cf46897616f3f70745726e95.png

    2.线程与进程的关系

    d4e0eb4d60d1f50d203c972b0bd043e1.png

    3.定义:

    cd8623331ca2d2208613fae8ca9d8eca.png

    区别:如上!!!

    4.wait()和sleep()

    17067a4a91996f8cd2070da82506bc97.png

    5.线程的状态及其他API

    ce52aee79da0a0512c460db96ac21047.png

    二、线程锁

    线程并发同步时,引入了锁机制。

    1. 普通锁机制:synchronized 修饰代码块与volatile 修饰成员变量

    a20e77210e448e4433bb86d5bc988d06.png

    2.Lock

    !!共同点:都是从外面创建锁类、再把锁传到线程里对变量对象赋值。

    (1)重入锁

    54f10be1fa79ce09719c9ecf96df1f26.png

    (2)读写分离锁

    af33ea693b0e9821e876f9a7020aa9e5.png

    区别:

    15e24eaec82e9700ea8a3bf23bb1d046.png

    二、线程同步工具类

    !!共同点:都是从外面创建工具类、再把工具类的参数传到线程里面执行。

    1.CountDowmLatch闭锁:等待所有线程执行完

    fef4c479868dde8eb9268062b0b0f4f6.png

    2.CyclicBarrier栅栏:等待所有线程达到后开启

    a4de383a5d0b46fe8af1d23f62d19487.png

    3.Exchanger交换机:交流数据

    d5c094bb91664cae3e713527dc13ef91.png

    4.信号量

    (1)概念

    21a7c9e6aaf7b32e6436b5082c52e6d6.png

    (2)应用场景一

    146288c0a2765252281e52f8a3f71e8a.png

    (3)应用场景二

    93eb014d2d4b2d60bfb7bdeb4c0fd23a.png

    三、线程池

    这里分享一个手写代码实现线程池的视频,需要代码的朋友可以后台私信【架构】获取

    线程池视频链接:手写代码现实线程池

    f17a1f557e35079d2e89cef24bcd8ac5.png

    1.为什么使用线程池

    ccb775ee870b260b855e1fdb9964f5dd.png

    2.线程池的核心队列

    阻塞式队列:只用于线程对象,主要用于引出线程池

    dd9b175027509b8e4dd23a5a234658f7.png

    3.手动创建线程池

    7ddadcc79f0e05f3936aa2de45fcef5c.png

    4.Executors工具创建线程

    核心线程:0(临时线程)、1(队列)、N(队列)

    71ab830ef441c1e2910f31490d33e3d3.png

    定时线程:

    a04f07b07c8aec05ee9b26ad4431420c.png

    四、彩蛋图

    93cb0df443a13f8a833b8dfc280e553e.png
    展开全文
  • 信号的实现是用一种称为信号量(Semaphore)的特殊变量。 信号量S就是一个特殊变量,包含一个整数值。 在S上可以执行两个原子操作:**wait(S)**用来接受信号,也称为P操作;**signal(S)**用来发送信号,也称为V操作...

    信号量方法的基本原则:两个或多个进程可以用信号的方法进行协作;进程可以在任何地方停下来以等待收到特定的信号;信号的实现是用一种称为信号量(Semaphore)的特殊变量。

    信号量S就是一个特殊变量,包含一个整数值。
    在S上可以执行两个原子操作:wait(S)用来接受信号,也称为P操作;signal(S)用来发送信号,也称为V操作。

    信号量分类:计数信号量(Counting Semaphore)、二元信号量(Binary Semaphore)、结构信号量(Structure Semaphore),

    结构型信号量

    结构型信号量数据结构

    typedef struct
    {
    	int value;
    	struct process *L;	// L指向一个进程队列
    }
    

    wait操作

    void wait(semaphore *S)
    {
    	s.value--;
    	if (s.value < 0)
    	{
    		add this process into S.L;
    		block();
    	}
    }
    

    signal操作

    void signal(semaphore *S)
    {
    	s.value++;
    	if (s.value <= 0)
    	{
    		remove a process P from S.L;
    		wakeup(P);
    	}
    }
    

    如何用信号量实现互斥?

    用信号量实现互斥的方法:
    (S.value初始值为1)
    wait(S);
    临界区
    signal(S);

    在这里插入图片描述
    例如:有三个进程P、Q、R欲进入临界区,S.value初始值为1。P进入时,先执行wait(S),此时S.value=0,不满足if条件,则wait结束,P进入临界区。若此时Q想要进入临界区,也需执行wait,此时S.value=-1,满足<0条件,则将进程加入S,L,block阻塞进程,使其等待。同理若R想进入临界区,则有S.value=-2,R进程也阻塞。
    此时若P从临界区出来,执行signal,此时S.value=-1,满足if条件,从等待进程中选择一个进入临界区,假设按照FCFS算法,使Q进入。同理Q出临界区后,S.value=0,R进入,R出临界区后,S.value=1,回归初始值。

    如何用信号量实现同步?

    用信号量实现同步的方法:
    S.value初始值为0
    在先执行的进程段后面加signal(S)
    后执行的进程段前面加wait(S)

    在这里插入图片描述
    例子:假设有P1和P2两个进程,要求P1进程的A段必须在P2进程的B段之前执行。
    (1) 若此时P1先执行,执行完A段后,执行signal(S),此时S.value=1,不满足signal中的if条件,不进行任何操作,结束signal。再执行P2的B段之前,执行wait(S),此时S.value=0,不满足wait中的if条件,不进行任何操作,结束wait,执行B。
    (2) 若此时P2先执行,执行B段之前先执行wait(S),此时S.value=-1,满足wait中的if条件,B段进入S.L队列,阻塞。执行P1中的A段,结束后执行signal(S),此时S.value=0,满足signal中的if条件,将B移出等待队列,唤醒B进程。

    信号量取值特点
    一个信号量的值可以为负数,其绝对值表示有多少个进程等待这个信号量。
    一个信号量的值可以为正数,表示有一个或多个被积累下来的唤醒操作。

    使用信号量时需要避免的错误
    死锁:两个或多个进程无限地等待一个事件,而这个事件只能由这些等待进程之一来产生。
    饥饿:无限期阻塞,即进程在信号内无限等待的情况。

    参考文献
    北京工业大学网课《操作系统原理》金雪云

    展开全文
  • 并发程序是应用开发中非常重要的一部分内容,如何实现程序的并发?包括多进程编程、进程间通信机制、多线程编程、线程间同步和异步机制等等。本次介绍多进程编程: fork创建进程 exit/_exit结束进程 exec函数族让...

    拥有梦想是一种智力,实现梦想是一种能力。

     

    概述

    并发程序是应用开发中非常重要的一部分内容,如何实现程序的并发?包括多进程编程、进程间通信机制、多线程编程、线程间同步和异步机制等等。本次介绍多进程编程:

    • fork创建进程
    • exit/_exit结束进程
    • exec函数族让进程执行指定程序
    • wait/waitpid回收一个已经结束了的进程
    • 如何创建一个守护进程

     

    系统调用fork允许一个进程(父进程)创建一个新进程(子进程)。通过fork,子进程几乎是父进程的复制版本,子进程获得父进程的栈、数据段、堆和执行文本段的拷贝。通常,调用fork产生子进程后,子进程随便会调用execve函数簇执行新的任务,随后执行exit相关函数退出。而父进程则通常会调用wait函数等待子进程终止。此外,我会通过程序的方向来介绍,如何让一个子进程脱离它原有的终端成为一个守护进程运行。

     

    fork()创建一个子进程

     pid_t  fork(void);

    • 创建新的进程,失败时返回-1
    • 成功时父进程返回子进程的进程号,子进程返回0
    • 通过fork的返回值区分父进程和子进程

     

    示例

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h> 
    
    int main()
    {
      pid_t  pid;
    
      if ((pid = fork()) < 0) {
         perror(“fork”);  
         return -1;
      }
      else  if (pid == 0) {//子进程执行
         printf(“child  process :  my pid  is %d\n”, getpid());
      }
      else {//父进程执行
         printf(“parent  process :  my pid  is  %d\n”, getpid());
      }  
    
      return 0;
    }

    此时,子进程fork()函数之后,而不是程序的开始处进行。由于子进程继承了父进程的所有内容,所以两个进程的执行没有差分。

     

    exit/_exit结束进程

     void  exit(int  status);
     void  _exit(int  status);

    • 结束当前的进程并将status返回

    exit与_exit的区别是,exit结束进程时会刷新(流)缓冲区。

     

    示例

    #include <stdio.h>
    #include <stdlib.h>
    
      int main(void) 
      {
         printf("this process will exit");//
         exit(0);
         printf("never  be  displayed");
      }
    

    由于shell终端是行缓冲输出,printf输出的字符串又没有换行,所以 "this process will exit" 会驻留在缓冲区。exit()操作会刷新缓冲区,终端显示   "this process will exit"。

     

    exec函数族让进程执行指定程序

      #include  <unistd.h>
      int execl(const char *path, const char *arg, …);
      int execlp(const char *file, const char *arg, …);
     

    •  成功时执行指定的程序;失败时返回EOF
    •  path   执行的程序名称,包含路径
    •  arg…  传递给执行的程序的参数列表
    •  file   执行的程序的名称,在PATH中查找
       

     进程调用exec函数族执行某个程序,进程当前内容被指定的程序替换。从而实现让父子进程执行不同的程序。

     

    示例

    #include <stdio.h>
    #include <unistd.h>
    
    int main()
    {
      if  (execl(“/bin/ls”, “ls”, “-a”, “-l”, “/etc”, NULL) < 0) 
      {
         perror(“execl”);
      }
    
      return 0;
    }  
    

     

    问:如何让父子进程执行不同程序?

    答:fork()创建一个子进程,然后exec()让进程执行其他程序,这样就达到了父子进程执行不同程序目的。

     

    wait/waitpid回收一个已经结束了的进程

    如果子进程结束了但是没有被回收的话,此时进程进入死亡态,叫做僵尸进程。僵尸进程的进程控制块依然存在(PCB),会占用资源,务必对其进行回收。通过父进程对其回收。

      #include  <unistd.h>
      pid_t wait(int *status);
       

    •  成功时返回回收的子进程的进程号;失败时返回EOF
    •  若子进程没有结束,父进程一直阻塞
    •  若有多个子进程,哪个先结束就先回收
    •  status 指定保存子进程返回值和结束方式的地址
    •  status为NULL表示直接释放子进程PCB,不接收返回值

     

    示例

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    int main()
    {
      int status;
      pid_t pid;
    
      if ((pid = fork()) < 0) {
         perror(“fork”);  
    	 exit(-1);
      }
      else if (pid == 0) {
         sleep(1);  
    	 exit(2);
      }
      else {
         wait(&status);  
    	 printf(“%x\n”, status);
      }
    
      return 0;
    }  
    

    wait()函数被父进程执行,父进程便进入阻塞态(一直等待),直到子进程结束。status保存子进程的返回值和结束方式地址。

     

     

    如何创建一个守护进程

    守护进程通常在系统启动时运行,系统关闭时结束。Linux很多服务程序以守护进程形式运行。其特点

    • 始终在后台运行
    • 独立于任何终端
    • 周期性的执行某种任务或等待处理特定事件

    Linux以会话(session)、进程组的方式管理进程。例如,我在打开shell(一个会话建立),运行一个脚本程序,然后关闭sell终端(会话关闭),程序也随之结束。而守护进程是不会随着终端关闭而结束的!!!

     

    示例

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <time.h>  
      
    int  main() {
    	pid_t pid;
    	FILE *fp;
    	time_t  t;
    	int  i;
    
    	if ((pid = fork()) < 0) 
    	{
    	  perror(“fork”);  
    	  exit(-1);
    	}
    	else if (pid > 0) 
    	{
    	   exit(0);
    	}
    	setsid();
    	umask(0);
    	chdir(“/tmp”);
    	for (i=0; i< getdtablesize(); i++) 
    	{
    	   close(i);
    	}
    	if ((fp = fopen(“time.log”, “a”)) == NULL) 
    	{
    	   perror(“fopen”); 
    	   exit(-1); 
    	}
    	while  ( 1 ) 
    	{
    	   time(&t);
    	   fprintf(fp, “%s”, ctime(&t));
    	   fflush(fp);
    	   sleep(1);
    	}   
    	 
    	return 0;
    }
    

     

    过程分析

     

    1.创建子进程,让子进程变成孤儿进程(杀死父进程)

        if ((pid = fork()) < 0) 
        {
          perror(¡°fork¡±);  
          exit(-1);
        }
        else if (pid > 0) 
        {
           exit(0);
        }


    2.使子进程脱离愿终端(原来子进程是建立在终端上的),切换终端操作

        setsid();

    3.重设文件掩码(推测是给进程创建文件的权限)

        umask(0);


    4.设定工作目录(让进程创建的文件一直存在)

    chdir()


    5.关闭子进程从 父进程那边 `继承`过来的文件

        for (i=0; i< getdtablesize(); i++) 
        {
           close(i);
        }

     

    展开全文
  • 文章目录线程 进程 协程start()与run()方法的区别Thread与Runnable的区别实现多线程的方法线程的状态与相互转换的方法为什么wait()notifyAll() notify() 只能在同步方法或者代码块中使用如何中断线程为什么stop 和...
  • 本文主要总结如何使用“kernel object”来实现线程间的同步。与用户模式下的同步方法相比,内核对象同步的效率会相对要低一些(需要切换到内核模式下),但是,它可以跨进程使用,而且在编程上也更简单。  除了...
  • 提供Process和Runnable两种方式实现进程 可以实时获取到进程状态 shutdown所有进程或单独stop一个进程时,可以注册覆盖beforeExit()方法,返回true则退出,false继续运行(在某些场景...
  • 同步通常是为了达到多线程协同的目的而设计的一种机制,通常包含异步信号机制和互斥机制作为其实现的底层。...我们从它的使用范例着手,看看等待队列是如何实现异步信号功能的。 在核心运行过程中,经常会因为某些
  • a.6 进程同步程序 附录b 线程入门 b.1 概述 b.2 基本线程函数:创建和终止 附录c 杂凑的源代码 c.1 unpipc.h头文件 c.2 config. h头文件 c.3 标准错误处理函数 附录d 部分习题解答 附录e 参考文献 附录f 函数...
  • 本书全面深入地讲解了各种进程间通信形式,包括消息传递、同步、共享内存及远程调用(RPC)。书中包含了大量经过优化的源代码,帮助读者加深理解。这些源代码可以从图灵网站本书网页免费注册下载。本书是网络研究和...
  • 如何实现多线程 怎么保证线程安全 wait、notify作用,使用场景,其他多线程同步工具或方法 如何实现join方法 实现同步的方式 线程池 线程池有几种创建方法 线程池种类 哪些场景用到fixedThreadpool 线程池状态 ...
  • java线程相关

    2020-02-03 15:34:34
    开启线程的三种方式? 线程和进程的区别? 为什么要有线程,而不是仅仅用进程? run()和start()方法区别 如何控制某个方法允许并发访问线程的个数?...如何实现线程同步? 两个进程同时要求写或者读,能不...
  • 线程: 1. 什么是进程 进程是操作系统中运行的一个任务 2. 什么是线程 3. 线程 ...sleep和wait的区别 ...解决线程同步安全问题的方法 ...如何实现多线程 线程池的优点和约点 ...
  • 北航面向对象Round Two

    2019-04-19 16:27:00
    1.三次作业设计策略 1.1第一次作业设计策略 ...​ 第一次作业主要遇到的问题是如何做到线程间共享变量的访问互斥,如何使用wait和notifyAll这两种函数实现进程同步。在仔细阅读了老师的PPT和网上的一些信息以...
  • 1,开启线程的三种方式?2,线程和进程的区别?3,为什么要有线程,而不是仅仅用进程?4,run()和start()方法的区别5,如何控制某个方法允许并发访问线程的个数?6,在java中wait和sleep方法...13,如何实现线程同...
  • 目录 概述 创建多线程 继承Thread类 实现Runnable接口 多线程安全问题 ...同步函数: ...同步代码块与同步函数的区别: ...静态同步函数: ...进程:正在执行中的程序,在内存中有自己的数据集合,进程控制块,每
  • 在上一篇《手把手教Linux驱动8-Linux IO模型》我们已经了解了阻塞、非阻塞、同步和异步等相关概念,本文主要讲解如何通过等待队列实现进程的阻塞。 应用场景: 当进程要获取某些资源(例如从网卡读取...
  • Java基础 ...Java中实现多态的机制是什么; 如何将一个Java对象序列化到文件里; 说说你对Java反射的理解; 同步的方法;多进程开发以及多进程应用场景; 在Java中wait和seelp方法的不同; synchro...
  • Java基础 1.进程和线程的区别; 2.Java的并发、多线程、线程模型; 3.什么是线程池,如何使用? ...4.数据一致性如何保证;Synchronized关键字,类锁,方法锁,重入锁;...5.Java中实现多态的机制是...9.在Java中wait和se
  • 如何实现Java多线程4.(重点)run方法与start方法有什么区别5.(重点)多线程同步实现的方法有哪些?6.sleep方法与wait方法的区别7.终止线程的方法都有哪些 1.什么是线程?他与进程的区别?为什么要用多线程 线程是...
  • Java基础1.进程和线程的区别;2.Java的并发、多线程、线程模型;3.什么是线程池,如何使用?4.数据一致性如何保证;Synchronized关键字,类锁,方法锁,重入锁;5.Java中实现多态的机制是什么;...9.在Java中wait...
  • Java基础 1.进程和线程的区别; 2.Java的并发、多线程、线程模型; 3.什么是线程池,如何使用? ...4.数据一致性如何保证;Synchronized关键字,类锁,方法锁,重入锁;...5.Java中实现多态的机制...9.在Java中wait和se...
  • 多线程(面试)

    2020-09-07 12:43:42
    进程与线程的区别?2. 为什么要用多线程?3. 多线程创建方式?4. 是继承Thread类好还是实现Runnable接口好?5. 你在哪里用到了多线程?6. 什么是多线程安全?7. 如何解决多线程之间线程安全问题?8. 为什么使用线程...
  • Java---腾讯面试题

    2019-04-06 19:13:16
    Java基础 ...5.Java中实现多态的机制是什么; 6.如何将一个Java对象序列化到文件里; 7.说说你对Java反射的理解; 8.同步的方法;多进程开发以及多进程应用场景; 9.在Java中wait和seelp方法的不同;...
  • 多线程

    2020-11-07 10:58:41
    多线程什么是单线程什么是进程什么是线程多线程的实现方式的3种步骤启动线程为什么是start而不是run方法Java能够开启线程吗?线程Tread类中的相关常用方法面试题:sleep(long time)和wait()方法的区别面试题:线程的...
  • 方法)== equals的区别Java的多线程同步方式(Lock类, synchonized, volatile)synchonized仔细讲一下(jvm指令, 锁优化, 和JUC的lock的区别)聊GC(新生代 老年代, 回收算法, 收集器)进程线程区别(linux中怎么实现)僵尸...

空空如也

空空如也

1 2 3 4
收藏数 78
精华内容 31
热门标签
关键字:

wait如何实现进程同步