站内搜索: 请输入搜索关键词

当前页面: 开发资料首页J2SE 专题关于sleep与wait区别的疑问

关于sleep与wait区别的疑问

摘要: 关于sleep与wait区别的疑问


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和2是用的两个不同的锁,即是this关键字,是线程所属的对象,两个锁互不影响


线程1和2是用的两个不同的锁 ??
不太理解,请说的详细一点!


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


当然是相同的锁。只不过你的程序写的有点问题,所以没有达到你的目标。
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;
}
}
}
这样写就不会出现了。
你的问题是同步放在循环内部,当一次循环结束的时候,同步锁就被释放了。


也许这样你看得更清楚:
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;
}
}
}
}


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


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


//当然是相同的锁。只不过你的程序写的有点问题,所以没有达到你的目标

对的!呵呵,楼主不好意思,是我看错了。。我以为是不同的锁了


楼主的程序是不同的锁,
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


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。


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


解释清楚些:
楼主的程序两个进程通过一把锁(ThreadTest t这个对象锁)进入synchronized代码,谁有锁,谁可以进入。

大家都可以进入run方法内直到“while(true){ ”的下一行,然后获得lock的那个Thread就可以进入sychronized()代码中。然后两个Thread就可能互相切换进入synchronized代码。

不知道楼主明白不了?


好多啊的帖子


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


呵呵,看来不是我一个人看错了 :)


...


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


关注下!

学习!


↑返回目录
前一篇: 请教一个关于对象初始化的问题!
后一篇: ObjectInputStream类和ObjectOutputStream类问题,高手指教啊!