精华内容
下载资源
问答
  • 进程的同步机制有哪几种

    千次阅读 2021-02-24 17:17:39
    1.什么是同步? 先说互斥,互斥:是指散布在不同任务之间...2.同步机制有哪几种? 互斥锁: 1)在访问共享资源后临界区域前,对互斥锁进行加锁。 2)在访问完成后释放互斥锁导上的锁。 3)对互斥锁进行加锁后,任何其他

    1.什么是同步?
    先说互斥,互斥:是指散布在不同任务之间的若干程序片断,当某个任务运行其中一个程序片段时,其它任务就不能运行它们之中的任一程序片段,只能等到该任务运行完这个程序片段后才可以运行。

    同步:是指散步在不同任务之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。

    综上,同步是更加严苛的互斥

    2.同步机制有哪几种?
    互斥锁: 1)在访问共享资源后临界区域前,对互斥锁进行加锁。 2)在访问完成后释放互斥锁导上的锁。 3)对互斥锁进行加锁后,任何其他试图再次对互斥锁加锁的线程将会被阻塞,直到锁被释放。

    读写锁:1)如果某线程申请了读锁,其它线程可以再申请读锁,但不能申请写锁。 2)如果某线程申请了写锁,其它线程不能申请读锁,也不能申请写锁。

    条件变量:条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。 条件变量的两个动作: 条件不满, 阻塞线程 当条件满足, 通知阻塞的线程开始工作

    信号量:信号量概述 信号量广泛用于进程或线程间的同步和互斥,信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。 编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限,当信号量值大于 0 时,则可以访问,否则将阻塞。 PV 原语是对信号量的操作,一次 P 操作使信号量减
    1,一次 V 操作使信号量加1。

    展开全文
  • 进程同步几种机制

    2015-08-26 21:29:38
    本讲将介绍进程间的两种主要关系——同步与互斥,然后着重讲解解决进程同步几种机制
  • 进程同步及线程同步几种机制

    万次阅读 2018-09-14 09:09:35
    1. 互斥量: 采用互斥对象机制,只有拥有互斥对象的线程才访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。 2. 信号量: 它允许同一时刻多个线程来访问同一资源,但是...

    进程中线程同步的四种常用方式:

    1. 互斥量: 采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。

    2. 信号量: 它允许同一时刻多个线程来访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。

    3. 事件(信号):通过通知操作的方式来保持多线程同步,还可以方便实现多线程优先级的比较作。

    4.临界区:临界区对象和互斥对象非常相似,只是互斥量允许在进程间使用,而临界区只限制与同一进程的各个线程之间使用,但是更节省资源,更有效率。

    临界区: 当多个线程访问一个独占性共享资源时,可以使用临界区对象。拥有临界区的线程可以访问被保护起来的资源或代码段,其他线程若想访问,则被挂起,直到拥有临界区的线程放弃临界区为止。

    1、 临界区(CCriticalSection)

    当多个线程访问一个独占性共享资源时,可以使用临界区对象。拥有临界区的线程可以访问被保护起来的资源或代码段,其他线程若想访问,则被挂起,直到拥有临界区的线程放弃临界区为止。具体应用方式:

                    1、 定义临界区对象CcriticalSection g_CriticalSection;

                    2、 在访问共享资源(代码或变量)之前,先获得临界区对象,g_CriticalSection.Lock();

                    3、 访问共享资源后,则放弃临界区对象,g_CriticalSection.Unlock();

     

    2、 事件(CEvent)

    事件机制,则允许一个线程在处理完一个任务后,主动唤醒另外一个线程执行任务。比如在某些网络应用程序中,一个线程如A负责侦听通信端口,另外一个线程B负责更新用户数据,利用事件机制,则线程A可以通知线程B何时更新用户数据。每个Cevent对象可以有两种状态:有信号状态和无信号状态。Cevent类对象有两种类型:人工事件和自动事件。

    自动事件对象,在被至少一个线程释放后自动返回到无信号状态;

    人工事件对象,获得信号后,释放可利用线程,但直到调用成员函数ReSet()才将其设置为无信号状态。在创建Cevent对象时,默认创建的是自动事件。

    1、

    1

    2

    3

    4

    CEvent(BOOL bInitiallyOwn=FALSE,

              BOOL bManualReset=FALSE,

              LPCTSTR lpszName=NULL,

              LPSECURITY_ATTRIBUTES lpsaAttribute=NULL);

    • bInitiallyOwn:指定事件对象初始化状态,TRUE为有信号,FALSE为无信号;
    • bManualReset:指定要创建的事件是属于人工事件还是自动事件。TRUE为人工事件,FALSE为自动事件;
    • 后两个参数一般设为NULL,在此不作过多说明。
    2、BOOL CEvent::SetEvent();

    将Cevent类对象的状态设置为有信号状态。如果事件是人工事件,则Cevent类对象保持为有信号状态,直到调用成员函数ResetEvent()将其重新设为无信号状态时为止。如果为自动事件,则在SetEvent()后将事件设置为有信号状态,由系统自动重置为无信号状态。

    3、BOOL CEvent::ResetEvent();

    将事件的状态设置为无信号状态,并保持该状态直至SetEvent()被调用为止。由于自动事件是由系统自动重置,故自动事件不需要调用该函数。

    一般通过调用WaitForSingleObject()函数来监视事件状态。

     

    3、 互斥量(CMutex)

    互斥对象和临界区对象非常相似,只是其允许在进程间使用,而临界区只限制与同一进程的各个线程之间使用,

    但是更节省资源,更有效率。

    4、 信号量(CSemphore)

     当需要一个计数器来限制可以使用某共享资源的线程数目时,可以使用“信号量”对象。CSemaphore类对象保存了对当前访问某一个指定资源的线程的计数值,该计数值是当前还可以使用该资源的线程数目。如果这个计数达到了零,则所有对这个CSemaphore类对象所控制的资源的访问尝试都被放入到一个队列中等待,直到超时或计数值不为零为止。

    CSemaphore 类的构造函数原型及参数说明如下:

    1

    2

    3

    4

    5

    6

    CSemaphore(

       LONG lInitialCount = 1,

       LONG lMaxCount = 1,

       LPCTSTR pstrName = NULL,

       LPSECURITY_ATTRIBUTES lpsaAttributes = NULL

    );

    • lInitialCount:信号量对象的初始计数值,即可访问线程数目的初始值;
    • lMaxCount:信号量对象计数值的最大值,该参数决定了同一时刻可访问由信号量保护的资源的线程最大数目;
    • 后两个参数在同一进程中使用一般为NULL,不作过多讨论;

    一般是将当前可用资源计数设置为最大资源计数,每增加一个线程对共享资源的访问,当前可用资源计数就减1,只要当前可用资源计数大于0,就可以发出信号量信号。如果为0,则放入一个队列中等待。线程在处理完共享资源后,应在离开的同时通过ReleaseSemaphore()函数将当前可用资源数加1。

     

    1

    2

    3

    BOOL ReleaseSemaphore(  HANDLE hSemaphore,       // hSemaphore:信号量句柄

                  LONG lReleaseCount,      // lReleaseCount:信号量计数值

                  LPLONG lpPreviousCount   // 参数一般为NULL);

    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    进程同步:

    多进程的系统中避免不了进程间的相互关系。本讲将介绍进程间的两种主要关系——同步与互斥,然后着重讲解解决进程同步的几种机制。 
          进程互斥是进程之间发生的一种间接性作用,一般是程序不希望的。通常的情况是两个或两个以上的进程需要同时访问某个共享变量。我们一般将发生能够问共享变量的程序段称为临界区。两个进程不能同时进入临界区,否则就会导致数据的不一致,产生与时间有关的错误。解决互斥问题应该满足互斥和公平两个原则,即任意时刻只能允许一个进程处于同一共享变量的临界区,而且不能让任一进程无限期地等待。互斥问题可以用硬件方法解决,我们不作展开;也可以用软件方法,这将会在本讲详细介绍。 
          进程同步是进程之间直接的相互作用,是合作进程间有意识的行为,典型的例子是公共汽车上司机与售票员的合作。只有当售票员关门之后司机才能启动车辆,只有司机停车之后售票员才能开车门。司机和售票员的行动需要一定的协调。同样地,两个进程之间有时也有这样的依赖关系,因此我们也要有一定的同步机制保证它们的执行次序。 
    本讲主要介绍以下四种同步和互斥机制:信号量、管程、会合、分布式系统。

    一,信号量

    参考自http://blog.csdn.net/leves1989/article/details/3305609

    理解PV:

    PV操作由P操作原语和V操作原语组成(原语是不可中断的过程),对信号量进行操作,具体定义如下:
        P(S):①将信号量S的值减1,即S=S-1;
               ②如果S³0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。
        V(S):①将信号量S的值加1,即S=S+1;
               ②如果S>0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。
    PV操作的意义:我们用信号量及PV操作来实现进程的同步和互斥。PV操作属于进程的低级通信。

    什么是信号量?信号量(semaphore)的数据结构为一个值和一个指针,指针指向等待该信号量的下一个进程。信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。注意,信号量的值仅能由PV操作来改变。
         一般来说,信号量S³0时,S表示可用资源的数量。执行一次P操作意味着请求分配一个单位资源,因此S的值减1;当S<0时,表示已经没有可用资源,请求者必须等待别的进程释放该类资源,它才能运行下去。而执行一个V操作意味着释放一个单位资源,因此S的值加1;若S£0,表示有某些进程正在等待该资源,因此要唤醒一个等待状态的进程,使之运行下去。

    利用信号量和PV操作实现进程互斥的一般模型是:
    进程P1              进程P2           ……          进程Pn
    ……                  ……                           ……
    P(S);              P(S);                         P(S);
    临界区;             临界区;                        临界区;
    V(S);              V(S);                        V(S);
    ……                  ……            ……           ……

        其中信号量S用于互斥,初值为1。
        使用PV操作实现进程互斥时应该注意的是:
        (1)每个程序中用户实现互斥的P、V操作必须成对出现,先做P操作,进临界区,后做V操作,出临界区。若有多个分支,要认真检查其成对性。
        (2)P、V操作应分别紧靠临界区的头尾部,临界区的代码应尽可能短,不能有死循环。
       (3)互斥信号量的初值一般为1。

    利用信号量和PV操作实现进程同步
    PV操作是典型的同步机制之一。用一个信号量与一个消息联系起来,当信号量的值为0时,表示期望的消息尚未产生;当信号量的值非0时,表示期望的消息已经存在。用PV操作实现进程同步时,调用P操作测试消息是否到达,调用V操作发送消息。
        使用PV操作实现进程同步时应该注意的是:

        (1)分析进程间的制约关系,确定信号量种类。在保持进程间有正确的同步关系情况下,哪个进程先执行,哪些进程后执行,彼此间通过什么资源(信号量)进行协调,从而明确要设置哪些信号量。
        (2)信号量的初值与相应资源的数量有关,也与P、V操作在程序代码中出现的位置有关。
        (3)同一信号量的P、V操作要成对出现,但它们分别在不同的进程代码中。

    【例1】生产者-消费者问题
    在多道程序环境下,进程同步是一个十分重要又令人感兴趣的问题,而生产者-消费者问题是其中一个有代表性的进程同步问题。下面我们给出了各种情况下的生产者-消费者问题,深入地分析和透彻地理解这个例子,对于全面解决操作系统内的同步、互斥问题将有很大帮助。

    (1)一个生产者,一个消费者,公用一个缓冲区。
    定义两个同步信号量:
    empty——表示缓冲区是否为空,初值为1。
       full——表示缓冲区中是否为满,初值为0。
    生产者进程
    while(TRUE){
    生产一个产品;
         P(empty);
         产品送往Buffer;
         V(full);
    }
    消费者进程
    while(True){
    P(full);
       从Buffer取出一个产品;
       V(empty);
       消费该产品;
       }
    (2)一个生产者,一个消费者,公用n个环形缓冲区。
    定义两个同步信号量:
    empty——表示缓冲区是否为空,初值为n。
    full——表示缓冲区中是否为满,初值为0。

        设缓冲区的编号为1~n-1,定义两个指针in和out,分别是生产者进程和消费者进程使用的指
    ,指向下一个可用的缓冲区。
    生产者进程
    while(TRUE){
         生产一个产品;
         P(empty);
         产品送往buffer(in);
         in=(in+1)mod n;
         V(full);
    }

    消费者进程
    while(TRUE){
     P(full);
       从buffer(out)中取出产品;
       out=(out+1)mod n;
       V(empty);
       消费该产品;
       }
    (3)一组生产者,一组消费者,公用n个环形缓冲区
        在这个问题中,不仅生产者与消费者之间要同步,而且各个生产者之间、各个消费者之间还必须互斥地访问缓冲区。
    定义四个信号量:
    empty——表示缓冲区是否为空,初值为n。
    full——表示缓冲区中是否为满,初值为0。
    mutex1——生产者之间的互斥信号量,初值为1。
    mutex2——消费者之间的互斥信号量,初值为1。

        设缓冲区的编号为1~n-1,定义两个指针in和out,分别是生产者进程和消费者进程使用的指针,指向下一个可用的缓冲区。
    生产者进程
    while(TRUE){
         生产一个产品;
         P(empty);
         P(mutex1);
         产品送往buffer(in);
         in=(in+1)mod n;
         V(mutex1);
         V(full);
    }
    消费者进程
    while(TRUE){
     P(full)
       P(mutex2);
       从buffer(out)中取出产品;
       out=(out+1)mod n;
       V(mutex2);
       V(empty);
       消费该产品;
       }
      需要注意的是无论在生产者进程中还是在消费者进程中,两个P操作的次序不能颠倒。应先执行同步信号量的P操作,然后再执行互斥信号量的P操作,否则可能造成进程死锁。

    【例2】桌上有一空盘,允许存放一只水果。爸爸可向盘中放苹果,也可向盘中放桔子,儿子专等吃盘中的桔子,女儿专等吃盘中的苹果。规定当盘空时一次只能放一只水果供吃者取用,请用P、V原语实现爸爸、儿子、女儿三个并发进程的同步。

    分析 在本题中,爸爸、儿子、女儿共用一个盘子,盘中一次只能放一个水果。当盘子为空时,爸爸可将一个水果放入果盘中。若放入果盘中的是桔子,则允许儿子吃,女儿必须等待;若放入果盘中的是苹果,则允许女儿吃,儿子必须等待。本题实际上是生产者-消费者问题的一种变形。这里,生产者放入缓冲区的产品有两类,消费者也有两类,每类消费者只消费其中固定的一类产品。

        :在本题中,应设置三个信号量S、So、Sa,信号量S表示盘子是否为空,其初值为l;信号量So表示盘中是否有桔子,其初值为0;信号量Sa表示盘中是否有苹果,其初值为0。同步描述如下:
    int S=1;
    int Sa=0;
    int So=0;
          main()
          {
            cobegin
                father();      /*父亲进程*/
                son();        /*儿子进程*/
                daughter();    /*女儿进程*/
            coend
        }
        father()
        {
            while(1)
              {
                P(S);
                将水果放入盘中;
                if(放入的是桔子)V(So);
                else  V(Sa);
               }
         }
        son()
        {
            while(1)
              {
                 P(So);
                 从盘中取出桔子;
                 V(S);
                 吃桔子;
                }
        }
        daughter()
        {
             while(1)
                {
                  P(Sa);
                  从盘中取出苹果;
                  V(S);
                  吃苹果;
                }

     
    思考题:

    四个进程A、B、C、D都要读一个共享文件F,系统允许多个进程同时读文件F。但限制是进程A和进程C不能同时读文件F,进程B和进程D也不能同时读文件F。为了使这四个进程并发执行时能按系统要求使用文件,现用PV操作进行管理,请回答下面的问题:
        (1)应定义的信号量及初值:                    。
        (2)在下列的程序中填上适当的P、V操作,以保证它们能正确并发工作:
         A()                B()                  C()                 D()
          {                 {                    {                  {
          [1];                [3];                  [5];                 [7];
          read F;             read F;                read F;              read F;
         [2];                [4];                  [6];                 [8];
          }                  }                    }                  } 

        思考题解答:
    (1)定义二个信号量S1、S2,初值均为1,即:S1=1,S2=1。其中进程A和C使用信号量S1,进程B和D使用信号量S2。
    (2)从[1]到[8]分别为:P(S1) V(S1) P(S2) V(S2) P(S1) V(S1) P(S2) V(S2)

     

     

    二,管程:参考自http://hi.baidu.com/zucenaa/blog/item/e63d22277c9d9c09918f9de2.html

    信号量机制功能强大,但使用时对信号量的操作分散,而且难以控制,读写和维护都很困难。因此后来又提出了一种集中式同步进程——管程。其基本思想是将共享变量和对它们的操作集中在一个模块中,操作系统或并发程序就由这样的模块构成。这样模块之间联系清晰,便于维护和修改,易于保证正确性。

    管程作为一个模块,它的类型定义如下: 
    monitor_name = MoNITOR; 
    共享变量说明; 
    define 本管程内部定义、外部可调用的函数名表; 
    use 本管程外部定义、内部可调用的函数名表; 
    内部定义的函数说明和函数体 

    共享变量初始化语句; 
    }

     

    从语言的角度看,管程主要有以下特性: 
    (1)模块化。管程是一个基本程序单位,可以单独编译; 
    (2)抽象数据类型。管程是中不仅有数据,而且有对数据的操作; 
    (3)信息掩蔽。管程外可以调用管程内部定义的一些函数,但函数的具体实现外部不可见; 
    对于管程中定义的共享变量的所有操作都局限在管程中,外部只能通过调用管程的某些函数来间接访问这些变量。因此管程有很好的封装性。 
    为了保证共享变量的数据一致性,管程应互斥使用。 管程通常是用于管理资源的,因此管程中有进程等待队列和相应的等待和唤醒操作。在管程入口有一个等待队列,称为入口等待队列。当一个已进入管程的进程等待时,就释放管程的互斥使用权;当已进入管程的一个进程唤醒另一个进程时,两者必须有一个退出或停止使用管程。在管程内部,由于执行唤醒操作,可能存在多个等待进程(等待使用管程),称为紧急等待队列,它的优先级高于入口等待队列。 
    因此,一个进程进入管程之前要先申请,一般由管程提供一个enter过程;离开时释放使用权,如果紧急等待队列不空,则唤醒第一个等待者,一般也由管程提供外部过程leave。 
    管程内部有自己的等待机制。管程可以说明一种特殊的条件型变量:var c:condition;实际上是一个指针,指向一个等待该条件的PCB队列。对条件型变量可执行wait和signal操作:(联系P和V; take和give) 
    wait(c):若紧急等待队列不空,唤醒第一个等待者,否则释放管程使用权。执行本操作的进程进入C队列尾部; 
    signal(c):若C队列为空,继续原进程,否则唤醒队列第一个等待者,自己进入紧急等待队列尾部。

     

    【示例】

    生产者-消费者问题(有buffer)

    问题描述:(一个仓库可以存放K件物品。生产者每生产一件产品,将产品放入仓库,仓库满了就停止生产。消费者每次从仓库中去一件物品,然后进行消费,仓库空时就停止消费。 
    解答: 
    管程:buffer=MODULE; 
    (假设已实现一基本管程monitor,提供enter,leave,signal,wait等操作)

      notfull,notempty:condition; // notfull控制缓冲区不满,notempty控制缓冲区不空; 
    count,in,out: integer;     // count记录共有几件物品,in记录第一个空缓冲区,out记录第一个不空的缓冲区 
    buf:array [0..k-1] of item_type; 
    define deposit,fetch; 
    use monitor.enter,monitor.leave,monitor.wait,monitor.signal;

     
    procedure deposit(item); 

      if(count=k) monitor.wait(notfull); 
      buf[in]=item; 
      in:=(in+1) mod k; 
      count++; 
      monitor.signal(notempty); 

    procedure fetch:Item_type; 

      if(count=0) monitor.wait(notempty); 
      item=buf[out]; 
      in:=(in+1) mod k; 
      count--; 
      monitor.signal(notfull); 
      return(item); 


    count=0; 
    in=0; 
    out=0; 


    进程:producer,consumer; 
    producer(生产者进程): 
    Item_Type item; 

      while (true) 
      { 
        produce(&item); 
        buffer.enter(); 
        buffer.deposit(item); 
        buffer.leave(); 
      } 


    consumer(消费者进程): 
    Item_Type item; 

      while (true) 
      { 
        buffer.enter(); 
        item=buffer.fetch(); 
        buffer.leave(); 
        consume(&item); 
      } 
    }

    【附】有关wait和signal的语言表示

    信号量结构使用C语言表示如下:

    1. typedef struct {
    2.     int value;//记录了这个信号量的值 
    3.     struct process *list;//储存正在等待这个信号量的进程 
    4. } semaphore;

    wait()信号量部分代码如下:

    1. wait(semaphore *S) {
    2.     S->value--;
    3.     if(S->value < 0) {
    4.         add this process to S->list;
    5.         block();
    6.     }
    7. }

    signal()信号量部分代码如下:

    1. signal(semaphore *S) {
    2.     S->value++;
    3.     if(S->value <= 0) {
    4.         remove a process P from S->list;
    5.         wakeup(P);
    6.     }
    7. }

    一、The Bounded-Buffer Problem:

    full初始化为0,empty初始化为n,mutex为1

    1. do{
    2.     wait(full);
    3.     wait(mutex);
    4.     ...
    5.     //remove an item from buffer to nextc
    6.     ...
    7.     signal(mutex);
    8.     signal(empty);
    9.     ...
    10.     //consume the item in nextc
    11.     ...
    12. while(TRUE);

    二、The Readers-Writers Problem:

    wrt初始化为1,readcount初始化为0,mutex为1

    写者操作: 

     

    1. do{
    2.     wait(wrt);
    3.     ...
    4.     //writing is performed 
    5.     ...
    6.     signal(wrt);
    7. while(TRUE);

     

     

    读者操作:

    1. do{
    2.     wait(mutex);//确保与signal(mutex)之间的操作不会被其他读者打断
    3.     readcount++;
    4.     if(readcount == 1)
    5.         wait(wrt);
    6.     signal(mutex);
    7.     ...
    8.     //reading is performed
    9.     ...
    10.     wait(mutex);
    11.     readcount--;
    12.     if(readcount == 0)
    13.         signal(wrt);
    14.     signal(mutex);
    15. while(TRUE);

     

     

     

    三、The Dining-Philosophers Problem:

     

    所有的chopstick[5]全部初始化为1

    1. do{
    2.     wait(chopstick[i]);
    3.     wait(chopstick[(i+1)%5]);
    4.     ...
    5.     //eating
    6.     ...
    7.     signal(chopstick[i]);
    8.     signal(chopstick[(i+1)%5]);
    9.     ...
    10.     //thinking
    11.     ...
    12. while(TRUE);

    但是这个解决方案的最大问题在于它会出现死锁。所以我认为应该增加一个信号量mutex,并初始化为1:

    1. do{
    2.     wait(mutex);
    3.     wait(chopstick[i]);
    4.     wait(chopstick[(i+1)%5]);
    5.     signal(mutex);
    6.     ...
    7.     //eating  
    8.     ...
    9.     wait(mutex);
    10.     signal(chopstick[i]);
    11.     signal(chopstick[(i+1)%5]);
    12.     signal(mutex);
    13.     ...
    14.     //thinking  
    15.     ...
    16. while(TRUE);

    这样由于确保了一位哲学家在拿起两只筷子的时间内其他哲学家不可以拿起任何一支筷子,从而破坏了死锁出现需要的四个特征中的Hold And Wait特征,从而避免了死锁的发生。

    展开全文
  • 列举几种进程的同步机制及优缺点

    千次阅读 2016-08-12 20:26:38
    而管程在少数几种编程语言之外又无法使用,并且,这些原语均未提供机器间的信息交换方法。 会合:
进程直接进行相互作用 分布式系统:
消息和rpc 由于在分布式操作系统中没有公共内存,因此参数全为值参, ...

    1)信号量机制:
一个信号量只能置一次初值,以后只能对之进行p操作或v操作。
    由此也可以看到,信号量机制必须有公共内存,不能用于分布式操作系统,这是它最大的弱点。
    2)自旋锁:
旋锁是为了保护共享资源提出的一种锁机制。
    调用者申请的资源如果被占用,即自旋锁被已经被别的执行单元保持,则调用者一直循环在那里看是否该自旋锁的保持着已经释放了锁
    自旋锁是一种比较低级的保护数据结构和代码片段的原始方式,可能会引起以下两个问题;
    (1)死锁
    (2)过多地占用CPU资源
    3)管程:
信号量机制功能强大,但使用时对信号量的操作分散,而且难以控制,读写和维护都很困难。因此后来又提出了一种集中式同步进程——管程。其基本思想是将共享变量和对它们的操作集中在一个模块中,操作系统或并发程序就由这样的模块构成。这样模块之间联系清晰,便于维护和修改,易于保证正确性。
    4)会合:
进程直接进行相互作用
    5)分布式系统:
由于在分布式操作系统中没有公共内存,因此参数全为值参,
    而且不可为指针。

    优缺点:
    信号量(Semaphore)及PV操作
优:PV操作能够实现对临界区的管理要求;实现简单;允许使用它的代码休眠,持有锁的时间可相对较长。
    缺:信号量机制必须有公共内存,不能用于分布式操作系统,这是它最大的弱点。信号量机制功能强大,但使用时对信号量的操作分散,而且难以控制,读写和维护都很困难。加重了程序员的编码负担;核心操作P-V分散在各用户程序的代码中,不易控制和管理;一旦错误,后果严重,且不易发现和纠正。
    自旋锁:
优:旋锁是为了保护共享资源提出的一种锁机制; 调用者申请的资源如果被占用,即自旋锁已经被别的执行单元保持,则调用者一直循环在那里看是否该自旋锁的保持者已经释放了锁; 低开销;安全和高效;
    缺:自旋锁是一种比较低级的保护数据结构和代码片段的原始方式,可能会引起以下两个问题;
    (1)死锁
    (2)过多地占用CPU资源
    传统自旋锁由于无序竞争会导致“公平性”问题
    管程:
优: 集中式同步进程——管程。其基本思想是将共享变量和对它们的操作集中在一个模块中,操作系统或并发程序就由这样的模块构成。这样模块之间联系清晰,便于维护和修改,易于保证正确性。
    缺:如果一个分布式系统具有多个CPU,并且每个CPU拥有自己的私有内存,它们通过一个局域网相连,那么这些原语将失效。而管程在少数几种编程语言之外又无法使用,并且,这些原语均未提供机器间的信息交换方法。
    会合:
进程直接进行相互作用
    分布式系统:
消息和rpc
    由于在分布式操作系统中没有公共内存,因此参数全为值参,
    而且不可为指针

    展开全文
  • 线程同步机制几种方法总结与对比 需要线程同步的原因: 当多个线程同时访问一个共享内存里面的变量时,有时会出现一个线程正在修改该变量的值,而其他的线程正在读取数据,可能就会导致错误。   实现线程...

    线程同步机制的几种方法总结与对比

    需要线程同步的原因:

    当有多个线程同时访问一个共享内存里面的变量时,有时会出现一个线程正在修改该变量的值,而其他的线程正在读取数据,可能就会导致错误。

     

    实现线程同步机制的方法:

    ·互斥量

    ·读写锁

    ·条件变量

     

    一. 互斥量

    互斥量从本质上说就是一把锁,在访问共享资源时,对互斥量加锁,访问完成后释放锁。对互斥量加锁以后,其他任何试图对互斥量再次加锁的线程会被阻塞直至当前线程释放互斥锁。

    相关函数可参考 APUE 教材。

     

    二. 避免死锁

    如果某个线程试图对同一个互斥量加锁两次,那么它将进入死锁状态,这个是比较明显的死锁产生状态。还有一些更加不明显的方式也能产生死锁。比如:程序使用多个互斥量时,如果允许 线程甲 一直占有第一个互斥量 A 并且在试图锁住第二个互斥量 B 时处于阻塞状态,但是拥有第二个互斥量 B 的线程 乙 也在试图锁住第一个互斥量 A 这时就会发生死锁。

     

    解决方法:可用过小心的控制互斥量加锁顺序来避免死锁。

    运用数据结构解决。

     

    三. 读写锁

    读写锁和互斥量类似,区别在于:互斥量只有两个状态,即锁住状态和不加锁状态,而且一次只有一个线程可以对其加锁。而读写锁可以有三个状态,读模式下加锁状态,写模式下加锁状态,不加锁状态。一次只能有一个线程占有写模式的读写锁,但可以由多个线程同时占有读模式的读写锁。

    读写锁非常适用于对数据结构读次数远大于写的情况。

    相关函数可参考 APUE 教材。

     

    四. 条件变量

    条件变量使我们可以睡眠等待某种条件出现。

    条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。

    相关函数可参考 APUE 教材。

    展开全文
  • 进程间通信有哪几种方式?

    千次阅读 2019-04-28 16:01:55
    无名管道( pipe ):管道是一半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。 高级管道(popen):将另一个程序当做一个新的进程在当前程序进程中...
  • 顾名思义,内核模式就是指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,而用户模式就是不需要切换到内核态,只在用户态完成操作。用户模式下的方法:原子操作(例如一个单一的全局变量),...
  • 进程同步的5种机制

    万次阅读 2018-08-24 09:04:04
    由此也可以看到,信号量机制必须公共内存,不能用于分布式操作系统,这是它最大的弱点。 (2)自旋锁 
旋锁是为了保护共享资源提出的一机制。调用者申请的资源如果被占用,即自旋锁被已经被别的执行单元...
  • java同步机制几种实现方式

    千次阅读 2017-03-26 14:38:43
    InheritableThreadLocal在原有基础上进行了扩展,包括其子线程在内的线程都可以实现数据的同步; synchronized synchronized修饰的代码块或是方法都可以看作是一个原子操作; 一个线程执行互斥代码的过程: 1....
  • 多线程同步机制几种方法

    万次阅读 2013-03-20 22:17:35
    Critical Section Critical section(临界区)用来实现... 不能够同时一个以上的 critical section 被等待。  无法侦测是否已被某个线程放弃。 可以实现线程间互斥,不能用来实现同步。 Semaphore Sema
  • 多线程-线程同步有几种实现方式

    千次阅读 2017-02-16 00:22:07
    线程同步有几种实现方式 1. Synchronized 在方法级别 public synchronized …. 在代码块 synchronized(对象){} 1. 当synchronized作用在方法上的时候,锁住的就是这个对象的实例 synchronized(this) 2. 当...
  • 进程间通信有哪几种方式

    千次阅读 2018-03-02 13:14:34
    无名管道( pipe ):管道是一半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。 高级管道(popen):将另一个程序当做一个新的进程在当前程序进程中...
  • 实现线程同步几种方式总结

    万次阅读 多人点赞 2018-07-25 21:31:26
    在这种情况下如何保证线程按照一定的顺序进行执行,今天就来一个大总结,分别介绍一下几种方式。 通过Object的wait和notify 通过Condition的awiat和signal 通过一个阻塞队列 通过两个阻塞队列 ...
  • 此时此刻才算刚刚开始:整个流程如图(生命周期): 1、订单提交成功 此时的订单状态默认为未确认... 那么它的生命周期正如上图中提交订单,它是单线操作,当支付成功,平台通过异步处理,回调机制获取到已支付...
  • Linux内核中的同步机制

    千次阅读 2018-08-26 15:54:06
    本文介绍Linux内核中的一些同步机制,通过本文,希望读者能够明白以下几点: 什么是同步 为什么要同步 同步的几种手段 1.什么是同步? 与其解释什么是同步,倒不如告诉读者同步的由来。在Linux内核中,同步技术...
  • 为何要使用同步? java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),  将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他...
  • 实现线程同步几种方法

    万次阅读 2018-09-27 09:50:52
    在多线程程序中,会出现多个线程抢占一个资源的情况,这时间可能会造成冲突,也就是一个线程可能还没来得及将更改的 资源保存,另一个线程的更改就开始了。可能造成数据不一致。因此引入多线程同步,也就是说多个...
  • 最近小扁我被问到 实现线程同步有哪几种方法,而我只知道使用同步关键字synchronized来实现而已(⊙o⊙),,所以必要来学习一下实现线程同步几种方法;各位看官,若非议(不接受反驳),请不吝赐教! 实现...
  • Qt同步线程的几种方法

    千次阅读 2015-07-27 09:14:56
    有几种情况:1、如果我只是看看的话,你也可以看,大家看到的都是正确的;2、如果我要看这个数据,你是不能改的,不然我看到的就不知道是什么了;3、我在改的时候,你不能看的,我可能会让你看到不正确的了;4、我在...
  • JAVA基本的同步机制

    千次阅读 2017-11-07 21:11:21
    这一小节主要介绍JAVA中哪些同步机制,下面个小节会分别介绍这些同步机制的用途,希望可以让大家对JAVA的同步机制有一定了解。好了,我们开始吧! (1)synchronized关键字,这个相信大家很了解,最好能理解其中...
  • windows系统多线程同步机制原理总结

    千次阅读 2018-12-24 21:24:33
    windows系统多线程同步机制原理总结 同步问题是开发过程中遇到的重要问题之一。...本文主要基于对《Windows内核原理与实现》一书相关章节的整理并结合自己的理解介绍同步机制的大概实现原理,任何...
  • 线程同步机制

    千次阅读 2019-02-14 17:52:46
    从广义上说,Java平台提供的线程同步机制包括锁、volatile关键字、final关键字、static关键字和一些相关的API,如Object.wait( )/.notify( )等   1、锁的概述和概念: a 线程安全问题的产生: 多个线程并发访问...
  • 进程间通信主要以下几种方式:管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。有名管道(named pipe):有名管道也是半双工...
  • 【线程同步的方式,有哪几种

    千次阅读 2018-03-23 20:06:51
    【1】同步代码方法 ...volatile关键字为域变量的访问提供了一免锁机制 【4】使用重入锁实现线程同步。reentrantlock类是可冲入、互斥、实现了lock接口的锁 他与sychronized方法具有相同的基本行为和语义 ...
  • 解决进程同步几种机制

    千次阅读 2012-03-20 10:51:24
    本讲将介绍进程间的两种主要关系——同步与互斥,然后着重讲解解决进程同步几种机制。  进程互斥是进程之间发生的一种间接性作用,一般是程序不希望的。通常的情况是两个或两个以上的进程需要同时访问某个共享...
  • 关于数据同步几种实现

    千次阅读 2018-08-08 09:11:08
    关于数据同步几种实现 转载:https://blog.csdn.net/xuemoyao/article/details/14002209 概述 关于数据同步主要两个层面的同步,一是通过后台程序编码实现数据同步,二是直接作用于数据库,在数据库层面实现...
  • 什么是线程同步?...实现同步机制有两个方法: 1。同步代码块: synchronized(同一个数据){} 同一个数据:就是N条线程同时访问一个数据。 2。 同步方法: public synchronized 数据返回类型 ...
  • java并发中常见的几种机制

    万次阅读 2016-12-10 16:06:48
    java并发中常见的几种机制。     1.偏向锁   偏向锁是JDK1.6提出来的一种锁优化的机制。其核心的思想是,如果程序没有竞争,则取消之前已经取得锁的线程同步操作。也就是说,若某一锁被线程获取...
  • java实现同步几种方式(总结)

    万次阅读 2018-05-09 11:53:05
    java实现同步几种方式(总结)为何要使用同步? java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 389,804
精华内容 155,921
关键字:

同步机制有哪几种