• Hour
    2019-03-22
    今天又用代码验证了下,终于明白为啥用while了!

    当线程被唤醒后,是从wait命令后开始执行的(不是从头开始执行该方法,这点上老师的示意图容易让人产生歧义),而执行时间点往往跟唤醒时间点不一致,所以条件变量此时不一定满足了,所以通过while循环可以再验证,而if条件却做不到,它只能从wait命令后开始执行,所以要用while

    百看不一练😂😂😂😂
    展开
     4
     71
  • 密码123456
    2019-03-16
    有hasen 是执行完,再去唤醒另外一个线程。能够保证线程的执行。hoare,是中断当前线程,唤醒另外一个线程,执行玩再去唤醒,也能够保证完成。而mesa是进入等待队列,不一定有机会能够执行。

    作者回复: 我觉得你真的理解了!!!!

     4
     64
  • 三圆
    2019-03-16
    看了三遍,终于明白了管程MESA模型了,刚开始一直在想线程T1执行出队是什么意思?到底是哪个队列,是入口等待队列,还是条件等待队列,后来理解了都不是。这个队列应该理解为JDK里面的阻塞队列,里面存在的是共享数据,线程T1,T2分别去操作里面的共享数据,执行数据的入队,出队操作,当然这些操作是阻塞操作。当线程T1对阻塞队列执行数据出队操作时,进入管程,发现阻塞队列为空,此时线程T1进入阻塞队列不为空这个条件的条件等待队列,此时,其他线程还是可以进入管程的,比如T2进来了,对阻塞队列执行数据插入操作,这时就会致使线程T1从条件等待队列出来,进入入口等待队列,准备再一次进入管程……至于wait方法的参数,还是有必要的,因为可能线程需要的条件可能一直无法满足!

    作者回复: 例子选的不好,让你误解了...

     8
     55
  • Geek_be4cec
    2019-08-01
    本节说的可能并不好。该篇我看了三遍也没能完全看懂,于是自己搜索java管程相关的技术文章,才大致对管程有了个认知,总结如下:
    1.管程是一种概念,任何语言都可以通用。
    2.在java中,每个加锁的对象都绑定着一个管程(监视器)
    3.线程访问加锁对象,就是去拥有一个监视器的过程。如一个病人去门诊室看医生,医生是共享资源,门锁锁定医生,病人去看医生,就是访问医生这个共享资源,门诊室其实是监视器(管程)。
    4.所有线程访问共享资源,都需要先拥有监视器。就像所有病人看病都需要先拥有进入门诊室的资格。
    5.监视器至少有两个等待队列。一个是进入监视器的等待队列一个是条件变量对应的等待队列。后者可以有多个。就像一个病人进入门诊室诊断后,需要去验血,那么它需要去抽血室排队等待。另外一个病人心脏不舒服,需要去拍胸片,去拍摄室等待。
    6.监视器要求的条件满足后,位于条件变量下等待的线程需要重新在门诊室门外排队,等待进入监视器。就像抽血的那位,抽完后,拿到了化验单,然后,重新回到门诊室等待,然后进入看病,然后退出,医生通知下一位进入。

    总结起来就是,管程就是一个对象监视器。任何线程想要访问该资源,就要排队进入监控范围。进入之后,接受检查,不符合条件,则要继续等待,直到被通知,然后继续进入监视器。
    展开

    作者回复: 👍

     1
     43
  • linqw
    2019-04-07
    管程的组成锁和0或者多个条件变量,java用两种方式实现了管程①synchronized+wait、notify、notifyAll②lock+内部的condition,第一种只支持一个条件变量,即wait,调用wait时会将其加到等待队列中,被notify时,会随机通知一个线程加到获取锁的等待队列中,第二种相对第一种condition支持中断和增加了时间的等待,lock需要自己进行加锁解锁,更加灵活,两个都是可重入锁,但是lock支持公平和非公平锁,synchronized支持非公平锁,老师,不知道理解的对不对

    作者回复: 总结很全面!

    
     27
  • Hour
    2019-03-22
    老师,针对条件变量的while循环,还是不太理解,您说是范式,那它一定是为了解决特定的场景而强烈推荐的,也有评论说是为了解决虚假唤醒,但唤醒后,不也是从条件的等待队列进入到入口的等待队列,抢到锁后,重新进行条件变量的判断,用if完全可以啊,为什么必须是while,并且是范式?

    望老师赐教!

    作者回复: code1;
    if (条件不满足)
      wait()
    code2;

    当调用wait()时,阻塞。被唤醒时,就直接执行code2了,没机会重新判断。

    
     22
  • 白马居士
    2019-04-05
    第一次看到MESA管程模型的时候很膈应,为什么要满足队列不空才能出队,在对照了《Java并发编程艺术》后,现在再看这一章才意识到“队列不空”只是人为的设置的条件A,只是为了说明管程支持多条件控制并发而自己设置控制条件的一个特例,是自己的设置,具体是什么与模型无关;初次看到这段还以为是MESA管程模型规定了“队列不空”这个出队条件,所以特别混乱。
    
     21
  • CCC
    2019-03-17
    MESA模型和其他两种模型相比可以实现更好的公平性,因为唤醒只是把你放到队列里而不保证你一定可以执行,最后能不能执行还是要看你自己可不可以抢得到执行权也就是入口,其他两种模型是显式地唤醒,有点内定的意思了。

    作者回复: 内定都出来了,真是理论联系生活

     1
     15
  • 佑儿
    2019-03-20
    老师,您好,结合第六讲,我的理解是:简单来说,一个锁实际上对应两个队列,一个是就绪队列,对应本节的入口等待队列,一个是阻塞队列,实际对应本节的条件变量等待队列,wait操作是把当前线程放入条件变量的等待队列中,而notifyall是将条件变量等待队列中的所有线程唤醒到就绪队列(入口等待队列)中,实际上哪个线程执行由jvm操作,我这样的理解对吗?

    作者回复: 对

     2
     13
  • 小李子
    2019-04-05
    wait() 不加超时参数,相当于得一直等着别人叫你去门口排队,加了超时参数,相当于等一段时间,再没人叫的话,我就受不了自己去门口排队了,这样就诊的机会会大一点,是这样理解吧?

    作者回复: 挺形象,就诊机会不一定大,但是能避免没人叫的时候傻等

    
     10
  • 虎虎❤️
    2019-03-16
    重新回答思考题,问题变成wait的timeout参数是否必要。

    在MESA模型中,线程T1被唤醒,从条件A的等待队列中(其实是一个set,list的话可能会重复)移除,并加入入口等待队列,重新与其他的线程竞争锁的控制权。那么有这样一种可能,线程T1的优先级比较低,并且经常地有高优先级的线程加入入口等待队列。每次当它获得锁的时候,条件已经不满足了(被高优先级的线程抢先破坏了条件)。即使T1可以得到调度,但是也没办法继续执行下去。

    最后T1被饿死了(有点冷。。。)

    另外我刚才的问题想通了。不需要实现像lock一样的条件对象,并调用condition.await(). Synchronized用判断条件+wait()就可以了。
    展开

    作者回复: 我觉得你已经能把管程的运作在大脑里演绎出来了!

    
     10
  • Healtheon
    2019-03-16
    感谢老师的精彩分享,谈一下个人对信号量和管程的理解。

    信号量机制是可以解决同步/互斥的问题的,但是信号量的操作分散在各个进程或线程中,不方便进行管理,因每次需调用PV操作,还可能导致死锁或破坏互斥请求的问题。

    管程是定义了一个数据结构和能为并发所执行的一组操作,这组操作能够进行同步和改变管程中的数据。这相当于对临界资源的同步操作都集中进行管理,凡是要访问临界资源的进程或线程,都必须先通过管程,由管程的这套机制来实现多进程或线程对同一个临界资源的互斥访问和使用。管程的同步主要通过condition类型的变量(条件变量),条件变量可执行操作wait()和signal()。管程一般是由语言编译器进行封装,体现出OOP中的封装思想,也如老师所讲的,管程模型和面向对象高度契合的。
    展开

    作者回复: 是的,管程只是一种解决并发问题的模型而已。

    
     9
  • 红衣闪闪亮晶晶
    2019-03-26
    老师,我能明白如果t1线程被唤醒后再次进入等待队列,但是可能再次走到条件变量那里再次因为条件不满足随后再次开始等待,所以需要增加超时,所以当我给wait加了超时,时间到了以后t1再次开始while中的判断,如果满足便自己回到入口等待队列?
    我这样理解对吗?

    作者回复: 如果没超时,A线程wait了,由于代码的bug,没有其他线程notify,就会导致A一直wait。增加超时之后,A线程可以自己来决定是否继续等待。这样代码的健壮性会更好

    
     8
  • 江南豆沙包
    2019-03-23
    老师,有个疑问,文中说到的条件变量,假如 synchronized(instance){做一些事情},这样一段代码,程序实际运行过程中条件变量是什么呢

    作者回复: 没用到条件变量,只有调用wait和notify的时候才会用到

    
     6
  • 饮识止渴(Vilin)
    2019-05-13
    线程wait超时后,会重新被放入入口队列,去争取锁吗?

    作者回复: 会

    
     5
  • 英耀
    2019-04-27
    王老师您好,我想请问一下文章中提到的是三种管程模型“hasen,hoare,mesa”是在什么资料(书籍、论文)中提到的呢?我想再深入了解这些管程模型的思想和原理,希望老师可以答疑解惑,感谢。

    作者回复: https://en.wikipedia.org/wiki/Monitor_(synchronization) 这个比较全面

    
     5
  • 大圣
    2019-07-23
    管程提出的太突兀了,没有从理论上给管程一个明确的定义,导致本章晦涩难懂。管程是一个理念还是一个工具?是JVM既定的实现还是需要人为自己实现,很多人会误以为管程是一个工具,用“管程”就能解决多线程问题。
     2
     3
  • dingdongfm
    2019-06-28
    看了很多遍,终于看明白了。文章里都是在用一个阻塞队列来举例子,而这个阻塞队列跟monitor里的队列没有关系。说清楚些会更好理解。
    
     3
  • the geek
    2019-04-24
    这一章给我的感觉是,告诉我们MESA的模型,然后可以自己手动实现管程了,说白了,当synchronize不满足我的需求时,可以自己写代码实现管程,还有并发包下的一些工具类可以辅助实现。
    
     3
  • life is short, e...
    2019-03-23
    好记性不如烂笔头
    管程定义:
    管理共享内存和操作共享内存的过程,令其支持并发。

    并发编程领域两大难题,互斥和同步。

    互斥如何保证:封装共享数据及其对应操作,每个操作任意时刻只允许一个线程执行。

    同步如何保证:使用MESA模型。

    MESA模型之前没接触过,只是能够按照老师的思路顺下来,还没有深刻的理解,希望老师在接下来的文章中,加深MESA的使用😄

    展开
    
     3
我们在线,来聊聊吧