Java线程同步 - Thread.sleep()方法不按预期工作

时间:2012-06-08 09:48:39

标签: java multithreading synchronization sync

我听说,sleep()将锁定当前的同步方法/块 但是在这里,当我在线程1上调用sleep()时,线程2能够访问同一个块吗?任何人都可以解释一下吗?

Main.java

public class Main {     
    public static void main(String args[])
    {
        Thread1 t1 = new Thread1();
        Thread2 t2 = new Thread2();
        System.out.println("going to start t1");
        t1.start();
        System.out.println("going to start t2");
        t2.start();

    }

}

=============================================== ======================

Thread1.java

public class Thread1 extends Thread{

    public void run() { 
        Syncc s1 = new Syncc();
        s1.me("T1:");
    }   

}

=============================================== ======================

Thread2.java

public class Thread2 extends Thread{

    public void run() { 
        Syncc s2 = new Syncc();
        s2.me("T2:");
    }   
}

=============================================== ======================

Syncc.java

public class Syncc{

    public void me(String s){
        synchronized(this){
        for(int i=0; i<=5; i++)
        {
            System.out.println(s+" "+" "+i);
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {              
                e.printStackTrace();
            }
        }
    }
}
}

==========================================

输出:

going to start t1
going to start t2
T2:  0
T1:  0
T2:  1
T1:  1
T1:  2
T2:  2
T1:  3
T2:  3
T1:  4
T2:  4
T2:  5
T1:  5

但是根据sleep()方法,它不应该解锁当前的同步块吗?如果是这样,输出应该是..

开始t1 将开始t2

T1:  0
T1:  1
T1:  2
T1:  3
T1:  4
T1:  5
T2:  0
T2:  1
T2:  2
T2:  3
T2:  4
T2:  5

我的意思是在线程1执行后只有线程2应该正确启动? 问题是什么?

3 个答案:

答案 0 :(得分:9)

这是因为你在这里有两个不同的Syncc实例。每个帖子都有自己的Syncc

副本

尝试对单个实例执行相同操作。您还可以在静态上下文中进行同步并尝试。

要模拟,修改Thread1Thread2以接受Syncc的实例。

public class Thread1 extends Thread {
    private Syncc syncc;

    public Thread1(Syncc syncc) {
        this.syncc = syncc;
    }

    public void run() { 
        this.syncc.me("T1:");
    }   
}

然后你可以这样启动它们:

public static void main(String args[]) {
    Syncc syncc = new Syncc();

    Thread1 t1 = new Thread1(syncc);
    Thread2 t2 = new Thread2(syncc);

    System.out.println("going to start t1");
    t1.start();
    System.out.println("going to start t2");
    t2.start();
}

答案 1 :(得分:2)

睡眠,产量和加入规则

  • 睡眠用于延迟执行一段时间,并且没有锁定 线程进入休眠状态时释放。

  • 保证睡眠线程至少在指定的时间内休眠 sleep()方法的参数(除非它被中断),但是有 无法保证新唤醒的线程何时会实际返回 运行

  • sleep()方法是一个静态方法,用于休眠当前正在执行的操作 线程的状态。一个线程无法告诉另一个线程休眠。

  • setPriority()方法用于Thread对象以提供线程 优先级介于1(低)和10(高)之间,但优先级不是 保证,并非所有JVM都识别10个不同的优先级 - 一些 水平可以被视为有效平等。

  • 如果没有明确设置,线程的优先级将具有相同的优先级 创建它的线程的优先级。

  • 如果存在,yield()方法可能会导致正在运行的线程退出 具有相同优先级的可运行线程。无法保证这一点 发生了,并且无法保证线程在那里退出 将是一个选择运行的不同线程。一个线程可能会产生然后 立即重新进入运行状态。

  • 最接近保证的是在任何给定时间,当一个线程 正在运行它通常没有比任何线程更低的优先级 可运行的状态。如果低优先级线程在高优先级线程时运行 进入runnable后,JVM通常会抢占正在运行的低优先级 线程并将高优先级线程放入。

  • 当一个线程调用另一个线程的join()方法时,当前 正在运行的线程将一直等到它加入的线程完成。认为 join()方法的说法,&#34;嘿线程,我想加入到最后 你的。让我知道你什么时候完成,所以我可以进入可运行状态。&#34;

http://www.amazon.com/SCJP-Certified-Programmer-Java-310-065/dp/0071591060

答案 2 :(得分:0)

您创建了两个Synch对象,每个对象对应一个线程。每个对象都有自己的副本。因此,当你启动每个线程时,使用run方法线程正在调用它自己的函数副本。由于两个线程只在它们的副本上起作用,因此它就像一个单线程场景。如果你想测试多线程场景,那么让方法为静态(类级方法)并应用类级锁。

<强> Thread1.java

public class Thread1 extends Thread{

public void run() { 
    Syncc.me("T1:");
}   

}

<强> Thread2.java

public class Thread2 extends Thread{

public void run() { 
    Syncc.me("T2:");
}   

}

<强> Syncc.java

public class Syncc{

public static void me(String s){
    synchronized(Syncc.class){
    for(int i=0; i<=5; i++)
    {
        System.out.println(s+" "+" "+i);
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {              
            e.printStackTrace();
        }
    }
}

} }