sleep与wait最大的区别之一是sleep()不释放资源,wait()释放资源
那么在线程1 sleep时,他并没有释放对象锁,哪线程2 是如何获得对象锁并运行的?
代码如下:public static void main(String[] args) {

MSTest a = new MSTest();
ThreadTest t= a.new ThreadTest();
new Thread(t,"1").start();
new Thread(t,"2").start();

}class ThreadTest implements Runnable{
private int tickets=10;
public void run(){
while(true){
synchronized(this){
if(tickets>0){
try{
Thread.sleep(1000);
}
catch(Exception e){
System.out.println(e.getMessage());
}
System.out.println(Thread.currentThread().getName()+"正在买第"+tickets--+"号票");
}
}
}
}
}运行结果如下:
1正在买第10号票
2正在买第9号票
1正在买第8号票
2正在买第7号票
1正在买第6号票
2正在买第5号票
1正在买第4号票
2正在买第3号票
1正在买第2号票
2正在买第1号票sleep与wait最大的区别之一是sleep()不释放资源,wait()释放资源
那么在线程1 sleep时,他并没有释放对象锁,哪线程2 是如何获得对象锁并运行的?

解决方案 »

  1.   

    线程1和2是用的两个不同的锁,即是this关键字,是线程所属的对象,两个锁互不影响
      

  2.   

    就是只锁当前的对象,每个线程中的对象不同,互不影响。
    synchronized(this)改成synchronized(this.getClass())试试看。
      

  3.   

    当然是相同的锁。只不过你的程序写的有点问题,所以没有达到你的目标。
    public synchronized void run() {
    while (true) {
    if (tickets > 0) {
    try {
    Thread.sleep(100);
    } catch (Exception e) {
    System.out.println(e.getMessage());
    }
    System.out.println(Thread.currentThread().getName() + "正在买第"
    + tickets-- + "号票");
    } else {
    break;
    }
    }
    }
    这样写就不会出现了。
    你的问题是同步放在循环内部,当一次循环结束的时候,同步锁就被释放了。
      

  4.   

    也许这样你看得更清楚:
    public void run() {
    synchronized (this) {
    while (true) {
    if (tickets > 0) {
    try {
    Thread.sleep(100);
    } catch (Exception e) {
    System.out.println(e.getMessage());
    }
    System.out.println(Thread.currentThread().getName()
    + "正在买第" + tickets-- + "号票");
    } else {
    break;
    }
    }
    }
    }
      

  5.   

    确实是相同的,原来想错了。
    但是这样仍然看不出sleep和wait的区别。
      

  6.   

    的确看不出来,因为,这里没有任何有关wait()的代码:)
    但是,sleep()的特点倒是可以看出来,就是它确实没有释放同步锁,从打印的结果可以看出:一个线程打印十行,另一个线程在它结束后,也默默无闻地结束了。
      

  7.   

    楼主的程序是不同的锁,
    new Thread(t,"1").start();
    new Thread(t,"2").start();
    这两句生成了两个不同的匿名对象,改成这样写就能看出区别:
    Thread thread1 = new Thread(t,"1");
    Thread thread2 = new Thread(t,"2");
    System.out.println(thread1);
    System.out.println(thread2);
    thread1.start();
    thread2.start();
    可以看到打印出的内容是不同的。synchronized(this)这句锁住的是当前的线程对象,所以两个线程锁住的对象分别是thread1和thread2。
    还有不明白为什么楼上的要这样写public synchronized void run()。
    run方法是Thread类的方法,我们定义的线程只要简单的覆盖run方法就行了,为什么要加上synchronized呢?(虽然synchronized不算方法签名的一部分)。
    楼主如果是想实现两个人买票,一人站在柜台前还没买完,另一人不能买票的情况,可以定义一个柜台内,在程序中实例化对象一个柜台对象,每个线程的买票动作都要对这个柜台对象上锁后才能完成,这样就自然实现了多个线程的同步。并且线程对柜台上锁后sleep,另一个线程不能买票,而线程对柜台上锁后的wait(),另一个线可以买票,这样就看出sleep和wait()的区别了。参见另一贴关于wait()和notify()的讨论:  :)
    http://community.csdn.net/Expert/TopicView3.asp?id=4790361
      

  8.   

    ThreadTest t= a.new ThreadTest();
    new Thread(t,"1").start();
    new Thread(t,"2").start();
    ==========
    我认为是一把锁,就是对象t的锁,谁拥有t这把object lock就可以进入run方法内的同步代码块。验证是一把锁也很简单,你在run方法的同步代码里写个for,然后打印1-20,可以加sleep方法延迟。如果是两把锁的话,两个进程间打印是切换的,如果是一把锁的话是连续的。
    结果可以证明,是连续的。进程1先输出1-20,然后进程2输出1-20。
      

  9.   

    楼主的错误在于把 synchronized 放到了while里面,导致两个进程可以交互进入while循环。然后JVM选择让谁进入Running状态
      

  10.   

    解释清楚些:
    楼主的程序两个进程通过一把锁(ThreadTest t这个对象锁)进入synchronized代码,谁有锁,谁可以进入。大家都可以进入run方法内直到“while(true){ ”的下一行,然后获得lock的那个Thread就可以进入sychronized()代码中。然后两个Thread就可能互相切换进入synchronized代码。不知道楼主明白不了?
      

  11.   

    呵呵,楼上正确,确实是一把锁,我没有看到两个匿名的线程对象都是以t为目标线程,同步块中的this就是t,而买票的行为能够交替进行的问题出在synchronized(this)应该套在while(true)的外面而不是里面,楼主的程序当线程1买完一张票后就释放锁,然后准备进入下一次循环再次获得锁,线程2就是在这个时候进入的。
      

  12.   

    各位大哥,我是新手,谁能告诉我为什么每次tickets都会自减啊?
    谢谢!
      

  13.   

    楼主你这个SB,老子白给你打那么字,一分不给老子。CAO