精华内容
下载资源
问答
  • 同步互斥异步回调这两个概念大家都不会陌生,学过计算机的人都知道跟进程,并发等等有关系。但如果真的深入下去,这两个概念都是大有文章可做的。我想结合最近自己工作的实际内容大致讲解下这两个概念,遇到的问题...

    最近的工作中遇到一些挑战,挑战中也找到了新的学习点。

    同步互斥与异步回调这两个概念大家都不会陌生,学过计算机的人都知道跟进程,并发等等有关系。但如果真的深入下去,这两个概念都是大有文章可做的。我想结合最近自己工作的实际内容大致讲解下这两个概念,遇到的问题以及解决的办法。一方面分享自己的观点,另一方面也给自己最近一段的工作做个总结。

    首先说同步互斥

    最近有个这样的业务,每次用户成功发起下单http请求后,程序在完成基本业务逻辑的同时,会创建一个异步回调请求来做一些耗时较长的统计任务(理论上一个下单请求只会统计一次)。这样可以避免http请求的超时,提高请求的成功率。但是却偶发地遇到异常情况,一个下单请求统计了两次。通过日志发现是异步回调服务出现偶发错误,并发了异步请求。这种情况说明异步回调服务和本地逻辑都存在问题。首先异步回调服务存在bug,异步服务采用的是redis队列的形式,正常情况下队列是一个一个处理的,但是却出现并发。其次本地程序没做好同步互斥,如果同步互斥做得好,完全可以避免这种并发的情况。

    最恰当地解决办法当然是本地逻辑做好同步互斥。异步回调请求中实际的业务逻辑是:首先检查MySQL数据表中回调状态(创建异步回调请求时,记录状态为创建中),如果状态是创建中,则往下修改统计数据表,修改完成后,则将回调状态更改为成功。当两个请求并发时,回调状态都为创建中,则会两次修改统计表。

    因为业务逻辑由php开发。php不支持多线程,所以没有从语言层面支持锁。此时想到的同步互斥解决办法有两种。一是加文件锁,flock来实现。不过文件锁机制会调用到宿主操作系统上的文件锁特性,因此在使用时一定要检查服务器操作系统是否为PHP环境提供了完善可靠的文件锁机制。二是利用MySQL的锁定机制来实现互斥。因为回调业务逻辑里面本身就是对mysql数据表操作,所以采用第二种方法来解决这个问题。

    回调请求检查回调状态时,MySQL加事务和行锁(for update)。首先解释事务:事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。例如,银行转账工作:从一个账号扣款并使另一个账号增款,这两个操作要么都执行,要么都不执行。所以,应该把它们看成一个事务。事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性。

    在回调业务中,会涉及到多个数据表的操作(回调状态的修改,统计表的修改)。如果执行过程中,任何一个数据库操作出现错误,会出现数据的不一致。举个极端的例子,如果最后修改回调状态因为某种原因一直失败,那么异步回调会一直请求,每次请求都会增加统计。加了事务,任何数据表操作失败,就会回滚所有的操作,避免了数据不一致的异常。

    再解释行锁(for update)。mysql执行select操作时,如果后面加上for update操作,该行就会被锁住。事务提交后,才能释放锁。

    在回调业务中,如果两个请求并发,第一请求读到该数据并加上行锁,第二个请求只能等第一个请求完成才能读取到数据。第一个请求完成后会把回调状态修改为成功。第二个请求在锁释放后,读取到回调状态为成功,就会返回,不做任何操作。通过事务+行锁,就避免了并发请求中数据库重复操作的情况。

    update:近期发现一个新的问题。数据库加行锁,容易出现死锁,导致请求彻底失败。为了解决这种情况,采用mc加锁的方式。add一条记录,请求完成,释放记录。如果并发过来的请求add记录,则会返回false。对add的记录加上过期时间,可避免死锁。具体可见timyang的一篇文章:Memcache mutex设计模式 – 后端技术 by Tim Yang。伪码(Pseudocode)见下面:if (memcache.get(key) == null) {

    // 3 min timeout to avoid mutex holder crash

    if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {

    value = db.get(key);

    memcache.set(key, value);

    memcache.delete(key_mutex);

    } else {

    sleep(50);

    retry();

    }

    }

    下面再讲异步回调

    异步回调不同于多线程,是一种类似消息或者事件的机制。 异步回调的作用主要是减轻主程序的负担,将一些cpu密集型的任务放在一个新进程中去执行。概念上理解很简单,但是在实际业务中用好异步回调却不是一件容易的事情。

    工作中有两块内容涉及到异步回调。首先是nodejs,nodejs是异步回调的典范。这种异步回调可以充分利用cpu的资源,提高程序的执行效率。但是在实际情况,异步回调也给开发者带来很大的困扰,第一个是程序排版问题,逻辑稍微复杂的程序,回调程序就会像一个斜下的瀑布一样难看。第二个是绝大部分程序不需要用到回调。有篇文章仔细讲解了nodejs的回调大坑-callback hell: http://www.infoq.com/cn/articles/nodejs-callback-hell/。为了避免这种问题,Node版本>=0.11.2提供了generator。generator属于一种迭代器,将异步回调顺序化。具体实现方式也可以参见上面链接。自从用了generator后,nodejs程序写的顺手多了,腰不酸了,腿不痛了,连加班都有兴趣了,~^-^~。

    第二块涉及到异步回调的内容在前面讲同步互斥时已经多次提起过。还是下单业务,创建异步回调请求时的逻辑。偶发出现的情况是回调了次数达到了限制,但统计数据没有更新。后来通过日志发现,回调程序在正常执行程序之前返回,但回调程序依赖正常执行程序逻辑,导致统计操作失败。这时的问题就是回调程序与正常执行程序的时序性出现偏差。更进一步总结就是顺序程序与回调程序之间的逻辑一定要搞清楚。后来的解决办法时,将回调程序依赖正常执行程序的那一部分放在异步回调任务创建之前。

    web开发中后端逻辑一般都很复杂,回调不好控制。这也是为什么nodejs写后端并不是很普及的原因。

    为了让大家能够更加明确地了解业务,我将新旧逻辑的架构图放在这里对比,大家看看架构的更改对同步互斥和异步回调带来了哪些改变。

    旧逻辑架构图:

    4e8b2a2392d0

    新逻辑架构图:

    4e8b2a2392d0

    展开全文
  • 同步 同步亦称直接制约关系,它是指为完成某种任务而建立的... 异步 异步的概念同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知回调来通知调用者。

    同步

    同步亦称直接制约关系,它是指为完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上协调它们的工作次序而等待、传递信息所产生的制约关系。进程间的直接制约关系就是源于它们之间的相互合作。一个进程的执行依赖于另一个协作进程的消息或信号,当一个进程没有得到来自于另一个进程的消息或信号时则需等待,直到消息或信号到达才被唤醒。

    简单来说,同步就是指在发出一个功能调用时,在没有得到结果之前,该调用就不返回。也就是必须一件一件事做,等前一件做完了才能做下一件事

    例如,输入进程A通过单缓冲向进程B提供数据。当该缓冲区空时,进程B不能获得所需数据而阻塞,一旦进程A将数据送入缓冲区,进程B被唤醒。反之,当缓冲区满时,进程A被阻塞,仅当进程B取走缓冲数据时,才唤醒进程A。

    互斥

    互斥亦称间接制约关系。当一个进程进入临界区使用临界资源时,另一个进程必须等待, 当占用临界资源的进程退出临界区后,另一进程才允许去访问此临界资源。

    进程互斥关系是一种特殊的进程同步关系,即逐次使用互斥共享资源,也是对进程使用资源次序上的一种协调。

    异步

    异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。

    展开全文
  • 1.1.9一个进程可以创建多少线程...1.2.1什么是线程同步和互斥 同步:线程间的同步指的是多个任务(线程)按照约定的顺序相互配合完成一件事情。 互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性排它

    1.一个进程可以创建多少线程,和什么有关

    系统参数限制:虽然 Linux 并没有内核参数来控制单个进程创建的最大线程个数,但是有系统级别的参数来控制整个系统的最大线程个数。

    进程的虚拟内存空间上限:因为创建一个线程,操作系统需要为其分配一个栈空间,如果线程数量越多,所需的栈空间就要越大,那么虚拟内存就会占用的越多。

    2.什么是线程同步和互斥

    同步:线程间的同步指的是多个任务(线程)按照约定的顺序相互配合完成一件事情。

    互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

    互斥锁更适合用于同时可用的资源是惟一的情况;信号量更适合用于同时可用的资源为多个的情况。

    3.线程同步与阻塞的关系?同步一定阻塞吗?阻塞一定同步吗?

    关系:同步是个过程,阻塞是线程的一种状态。例如:多个线程操作共享变量时可能会出现竞争。这时需要同步来防止两个以上的线程同时进入临界区,在这个过程中,后进入临界区的线程将阻塞,等待先进入的线程走出临界区。

    线程同步不一定发生阻塞!线程同步的时候,需要协调推进速度,互相等待和互相唤醒会发生阻塞。

    阻塞也不一定同步。

    4.并发,同步,异步,互斥,阻塞,非阻塞的理解

    并发:是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行。其中两种并发关系分别是同步和互斥。

    同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问

    异步:异步和同步是相对的。异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这一事件完成后再工作。

    阻塞方式下读取或者写入函数将一直等待而非阻塞方式下,读取或者写入函数会立即返回一个状态值。

    同步阻塞IO :用户进程在发起一个IO操作以后,必须等待IO操作的完成,只有当真正完成了IO操作以后,用户进程才能运行。

    同步非阻塞IO :用户进程发起一个IO操作以后可返回做其它事情,但是用户进程需要时不时的询问 IO操作是否就绪,这就要求用户进程不停的去询问,从而引入不必要的CPU资源浪费。

    异步阻塞IO :应用发起一个IO操作以后,不等待内核IO操作的完成等内核完成IO操作以后会通知应用程序,这其实就是同步和异步最关键的区别同步必须等待或者主动的去询问IO是否完成。

    异步非阻塞IO :用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知, 此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作因为真正的IO读取或者写入操作已经由内核完成了。

    展开全文
  • 同步与异步的概念 多线程开发可能遇到的问题:多个线程抢一个资源 什么是同步:同步就是协同步调,按预定的先后次序进行运行。如:你说完,我再说。 "同"字从字面上容易理解为一起动作 其实不是,"同"字应是指协同、...

    同步与异步的概念

    多线程开发可能遇到的问题:多个线程抢一个资源

    什么是同步:同步就是协同步调,按预定的先后次序进行运行。如:你说完,我再说。

    "同"字从字面上容易理解为一起动作

    其实不是,"同"字应是指协同、协助、互相配合。

    如进程、线程同步,可理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行;B依言执行,再将结果给A;A再继续操作。

    在计算机领域,同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。

    而我们平时经常讨论的同步问题多发生在多线程环境中的数据共享问题。即当多个线程需要访问同一个资源时,它们需要以某种顺序来确保该资源在某一特定时刻只能被一个线程所访问,如果使用异步,程序的运行结果将不可预料。因此,在这种情况下,就必须对数据进行同步,即限制只能有一个进程访问资源,其他线程必须等待。

    实现同步的机制主要有临界区、互斥、信号量和事件

    临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资 源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。

    互斥量:采用互斥对象机制。 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享 .互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。

    信号量:它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目 。信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中的PV操作相同。它指出了同时访问共享资源的线程最大数目。它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。

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

    互斥

    当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制

    线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。

    互斥锁为资源引入一个状态:锁定/非锁定。

    某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

    死锁

    由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁

    在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。

    死锁的四个必要条件
    互斥条件:一个资源每次只能被一个进程使用,即在一段时间内某 资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。

    请求与保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。

    不可剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。

    循环等待条件: 若干进程间形成首尾相接循环等待资源的关系

    这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

    展开全文
  • 并发,同步,互斥异步,阻塞,非阻塞的理解 并发(concurrency):在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行。其中两种并发关系分别是同步...
  • 互斥锁保证了每次只有一个线程进入写入操作,从而保证了多线程情况下数据的正确性。采用f_flag的方法效率低创建锁mutex=threading.Lock()锁定mutex.acquire([blocking])#里面可以加blocking(等待...
  • 同步接口和异步接口

    2021-03-17 12:50:47
    定义答案:来自网络搜索同步调用:当一个支付请求被发送到...使用场景异步的使用场景:1、不涉及共享资源,或对共享资源只读,即非互斥操作2、没有时序上的严格关系3、不需要原子操作,或可以通过其他方式控制原子性...
  • 进程同步和互斥

    2020-12-31 13:34:13
    在描述一个程序时,我们总是认为内部有一个“小人”,可以按程序所规定的步骤来执行程序。然而,在实际的系统中并不是这样。正如之前所讲,即使在程序中所描述的一条简单语句,也是由多条执行...互斥一组并发进程...
  • 进程的同步和互斥

    2021-06-05 20:52:11
      我们把异步环境下的一组并发进程因直接制约而互相发送消息、进行互相合作、互相等待,使得各进程按一定的速度执行的过程称为进程间的同步。具有同步关系的一组并发进程称为合作进程,合作进程间互相发送的信号...
  • 互斥锁: 同一时刻只能有一个线程获得互斥锁,其余线程处于挂起状态.2. 自旋锁: 当某个线程获得自旋锁后,别的线程会一直做循环,尝试加锁,当超过了限定的次数仍然没有成功获得锁时,线程也会被挂起.自旋锁较适用于锁的...
  • java中的同步和异步

    2021-02-12 14:30:51
    获得它可以保证在同- -时刻只有一-个线程能够进入临界区(访问互斥资源的代码块),并且在这个锁被释放之前,其他线程就不能再进人这个临界区。如果还有其他线程想要获得该对象的锁,只能进人等待队列等待。只有当...
  • 我回答了一个听起来与您的问题惊人相似的问题,其中有人有一个家庭作业来创建一个客户机-服务器设置,每个连接都在一个新线程中处理:...关于异步与线程的额外信息There are only two w...
  • yield()的作用是让步,它能够让当前线程从“运行状态”进入到“就绪状态”,从而让其他等待线程获取执行权,但是不能保证在当前线程调用yield()之后,其他线程就一定能获得执行权,也有可能是当前线程又回到“运行...
  • 互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这个资源。比如对全局变量的访问,有时要加锁,操作完了,在解锁。有的时候锁...
  • 尽管所有的生产者进程消费者进程都是以异步方式运行的,但它们之间必须保持同步,既不允许消费者进程到一个空缓冲区去取产品,也不允许生产者进程向一个已装满产品且尚未被取走的缓冲区中投放产品。请利用信号量来...
  • 互斥锁保证了每次只有一个线程进入写入操作,从而保证了多线程情况下数据的正确性。采用f_flag的方法效率低(上一篇文章最后)创建锁mutex=threading.Lock()锁定mutex.acquire([blocking])#里面可以加bl...
  • (2)其他函数。int sem_wait (sem_t* sem);int sem_trywait(sem_t* sem);int sem_post (sem_t* sem);int sem_getvalue (sem_t* sem);int sem_destroy (sem_t...功能:sem_waitsem_trywait相当于P操作,它们都能将信...
  • 程序里面的同步和异步和我们现实生活理解不太一样,一般我们对同步的理解是同时做很多事情,但程序中的同步是按照任务的顺序执行任务,前一个任务没有执行结束,下一个任务不会执行,要等待上一个任务执行结束。...
  • 并发行带来了异步性,有时需要通过进程同步解决这种异步问题。 有的进程之间需要相互配合的完成工作,各进程的工作推进需要遵循一定的先后顺序。 二、进程互斥 进程的“并发”需要“共享”的支持。各个并发执行的...
  • 没有协调对资源的访问的本地内核 消息传递是实现分布式互斥的唯一手段 算法必须处理不可预测的消息延迟系统状态的不完整知识。 例子 对共享文件的一致访问(例如,网络文件系统) 以太网中的媒体访问控制 假设 ...
  • 1、线程模型1)线程异步:多个线程之间独立执行,谁也不用等谁线程同步:一个线程必需等另外一个线程执行完毕之后才能执行备注:为了数据的安全,尽管应用程序的使用率低,但是为了保证数据是安全的,必须加入线程...
  • 互斥互斥锁保证某一时刻,只能在一处获取锁,当当前线程拥有锁时,其他线程...底层的实现原理是包装了pthread_mutex_t结构体,并调用pthread_mutex_lockpthread_mutex_unlock完成加锁解锁的功能。其内存布局: t
  • 首先我们来说一下同步是什么:其实...但是一般而言,我们在说同步、异步的时候,特指那些需要其他部件协作或者需要一定时间完成的任务。例如Window API函数SendMessage。该函数发送一个消息给某个窗口,在对方处理完...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 59,638
精华内容 23,855
关键字:

互斥和异步