• echo-coco
    2019-10-11
    老师您好
         有一个问题不是很清楚,希望能帮我解答一下。
         既然说synchronized是不公平锁,那么对于这个样例程序里除了main以外的五个线程,4s左右,第二个thread结束sleep准备调用wait方法时,此时,main thread应该已经结束了3s的sleep,运行到notify的synchronized代码块,所以main thread 应该要和剩下的其余3个thread一起争抢locker的monitor,所以应该有可能出现main thread先抢到locker的monitor的情况,导致程序运行出错,但是我试了几次发现,程序总是在5个子线程都抢到locker的monitor之后,main thread才能拿到locker的monitor依次唤醒5个子线程,这是为什么呢?
    展开

    作者回复:
    是这样的,synchronized不保证(强调不保证)是公平锁。但是并不代表实际在某个具体程序的某次运行时,他的表现是和公平锁一样的。

    只要有不公平的可能,就不能说是公平锁。要能百分之百保证在任何情况下都是公平锁,代价很高。synchronized是随缘公平,不保证公平。

    
     2
  • 寄风长存グ
    2020-02-06
    老师您好,我想问一下,在主线程延时1秒的情况时,当主线程执行到延时一秒后(sleepSec(workingSec - 1)),执行synchronized代码块时,因为子线程还在两秒钟sleep占用锁,所以主线程会等待锁的释放,当第一个子线程sleep完两秒后进入wait状态进而释放锁,这时候有剩余的四个子线程和主线程在抢锁,但是我每次测试都发现主线程总是先执行那五个唤醒,然后在执行那四个子线程,(1)按理说如果synchronized存在公平锁的现象时,那四个线程先请求的锁,主线程后请求,应该先执行子线程啊,为啥每次都是主线程(难道是主线程先抢占的?),(2)如果是不公平锁的现象,这几个线程都有可能先执行,但是还是主线程先执行。请问这是怎么回事?

    作者回复: synchronised是不公平锁。主线程也没有什么优先权。现象一样还是因为代码太简单,也没有引入随机因素(不敢乱搞,否则录视频的时候太乱)。你可以试试看把sleepSec改成下面的样子,运行的结果就会有意思一点。


      private static void sleepSec(int sec) {
        try {
          Thread.sleep(TimeUnit.SECONDS.toMillis(sec) + (int) (Math.random() * 200));
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }

    
    
  • WEgeeker
    2019-09-16
    为什么感觉除了第一个抢到锁wait的线程sleep了两秒,其他的线程并没有sleep两秒(除了主线程)

    作者回复:
    第一个线程在sleep的时候,别的线程也在sleep呀

     2
    
  • 消融
    2019-08-24
    sleepSec(workingSec + 1);睡三秒跟一秒有什么差别啊,每个线程抢到锁不都要睡2秒吗,睡三秒不就是2个线程抢先吗,那还有三个线程与主线程抢啊。可是我运行了好几遍主线程都是最后一个抢到?

            System.out.println("------------- 唤醒线程sleep结束 -------------");

            synchronized (locker) {睡3秒之后这个不是也加入抢锁吗,睡一秒后可以抢,睡三秒应该也行吧可是我运行了好几遍都是最后一个抢到?

                // >> TODO notify/notifyAll 方法必须在进入相应对象的synchronized块中才能调用

              System.out.println("------------- 开始唤醒所有 -------------");

               locker.notifyAll();
    展开
     1
    
  • 消融
    2019-08-23
    sleepSec(workingSec + 1);

            System.out.println("------------- 唤醒线程sleep结束 -------------");

            synchronized (locker) {睡3秒之后这个不是也加入抢锁吗,睡一秒后可以抢,睡三秒应该也行吧可是我运行了好几遍都是最后一个抢到?

                // >> TODO notify/notifyAll 方法必须在进入相应对象的synchronized块中才能调用

              System.out.println("------------- 开始唤醒所有 -------------");

               locker.notifyAll();
    展开
    
    
  • 消融
    2019-08-22
    sleepSec(workingSec + 1);

            System.out.println("------------- 唤醒线程sleep结束 -------------");

            synchronized (locker) {睡3秒之后这个锁不是也加入抢锁,我运行了好几遍都是最后一个抢到?

                // >> TODO notify/notifyAll 方法必须在进入相应对象的synchronized块中才能调用

              System.out.println("------------- 开始唤醒所有 -------------");

               locker.notifyAll();
    展开

    作者回复: sleep不会失去synchronized锁

    
    
我们在线,来聊聊吧