简体   繁体   English

睡完后什么线程? 在思考 leetcode 问题时:按顺序打印

[英]What thread does after finishing sleeping? while thinking leetcode question: Print in Order

I am doing leetcode question: https://leetcode.com/problems/print-in-order/ and try different solution here:我正在做 leetcode 问题: https://leetcode.com/problems/print-in-order/并在这里尝试不同的解决方案:

// Solution 1:
// 25 ms time
// The first solution is slower? Probably because waking up a thread is more costly. The second solution is more close to positive lock. 
class Foo {
    
     int lockSecond = 0;
     int lockThird = 0;

    public Foo() {
        
    }

    public synchronized void first(Runnable printFirst) throws InterruptedException {
        
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        this.lockSecond = 1;
        notifyAll();
    }

    public synchronized void second(Runnable printSecond) throws InterruptedException {
        
        for (;this.lockSecond == 0;) {
            wait();
        }
        
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        this.lockThird = 1;
        notifyAll();
    }

    public synchronized void third(Runnable printThird) throws InterruptedException {
        for (;this.lockThird == 0;) {
             wait();
        }
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
        notifyAll();
    }
}
//Solution 2:
//10 ms there is no valotile, which means thread will retieve latest value when finishing sleeping
class Foo {
    
    int lockSecond = 0;
    int lockThird = 0;

    public Foo() {
        
    }

    public void first(Runnable printFirst) throws InterruptedException {
        
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        this.lockSecond = 1;
    }

    public void second(Runnable printSecond) throws InterruptedException {
        
        for (;this.lockSecond == 0;) {
            Thread.sleep(1);
        }
        
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        this.lockThird = 1;
    }

    public void third(Runnable printThird) throws InterruptedException {
        for (;this.lockThird==0;) {
           Thread.sleep(1);
        }
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }
}
// same as second solution, 
//Solution 3:
class Foo {
    
    volatile int lockSecond = 0;
    volatile int lockThird = 0;

    public Foo() {
        
    }

    public void first(Runnable printFirst) throws InterruptedException {
        
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        this.lockSecond = 1;
    }

    public void second(Runnable printSecond) throws InterruptedException {
        
        for (;this.lockSecond == 0;) {
        }
        
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        this.lockThird = 1;
    }

    public void third(Runnable printThird) throws InterruptedException {
        for (;this.lockThird==0;) {
        }
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
    }
}

I can understand we use volatile to make the var shared across different thread in solution 3 to avoid the endless loop.我可以理解我们使用 volatile 使解决方案 3 中的不同线程共享 var 以避免无限循环。 If I remove volatile, Leetcode will say exceeding time limit.如果我删除 volatile,Leetcode 会说超出时间限制。

But for solution 2, I can remove volatile if I use sleep.但是对于解决方案 2,如果我使用睡眠,我可以删除 volatile。 Does this mean thread will always re-read value of variable after finishing sleep, which avoid the time limit issue?这是否意味着线程在完成睡眠后总是会重新读取变量的值,从而避免时间限制问题? Not familiar with multi-threading, there might be misleading comments in the code snippet.不熟悉多线程,代码片段中可能存在误导性注释。 Welcome any correcting!欢迎大家指正! ----------------------Update -------------------------------- - - - - - - - - - - - 更新 - - - - - - - - - - - - - - -----

It has nothing to do with sleep() actually.它实际上与 sleep() 无关。 It is up to whether there is statement in the for loop body.取决于for循环体中是否有语句。 If I replace sleep with println(), it still passes test cases.如果我用 println() 替换 sleep,它仍然通过测试用例。 If it is empty, it will exceed time.如果它是空的,它将超过时间。 Actually in my opinion, if there is no valotile keyword.实际上在我看来,如果没有 valotile 关键字。 It will get into endless loop since different thread share no visibility but it doesn't.它将进入无限循环,因为不同的线程不共享可见性,但事实并非如此。 It just gets slower.它只是变得更慢。 When there is a statement, it can even pass the tests case of leetcode当有语句时,它甚至可以通过 leetcode 的测试用例

Thread.sleep(n) is not guaranteed to do anything except not return until either n milliseconds have elapsed, or the calling thread was interrupted. Thread.sleep(n)保证做任何事情,除非在n毫秒过去或调用线程被中断之前不返回。 Anything else that happens when you call it either is a peculiarity of whatever JRE, JVM, and OS version you are using, or else it's a roll of the dice on whatever JRE, JVM, and OS version you are using.当您调用它时发生的任何其他事情都是您使用的任何 JRE、JVM 和操作系统版本的特性,或者它是您使用的任何 JRE、JVM 和操作系统版本的骰子。

If your code depends on sleep() for any kind of synchronization or coordination between different threads, then you are taking a risk that it won't work everywhere and/or it won't work every time.如果您的代码依赖于sleep()来实现不同线程之间的任何同步或协调,那么您将面临它无法在任何地方工作和/或每次都无法工作的风险。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM