我知道while(true)放在调用同步方法sale()的地方程序运行是正确的,我想请大家帮我分析一下,当while(true)放在同步方法内,为什么只会启动第一个线程(Thread0),而其他线程不会启动。程序如下:(可将下面代码拷贝运行一下就会发现问题,问题是只有Thread0在运行,即只有一个窗口售票。)/*模拟售票窗口售票,每个线程是一个窗口,变量ticket是100张票共创建了4个线程,
*即4个窗口卖100张票*/
class NewThread
{
public static void main(String [] args)
{
TestThread tt=new TestThread(); //创建了4个线程,模拟4个售票窗口
Thread t1=new Thread(tt);
Thread t2=new Thread(tt);
Thread t3=new Thread(tt);
Thread t4=new Thread(tt);
t1.start();
t2.start();
t3.start();
t4.start();
}
}class TestThread implements Runnable
{
int ticket=100; //共同出售100张票
public void run()
{
sale();
}
public synchronized void sale() //定义同步方法
{
while(true)
{
if(ticket>0)
{
try{Thread.sleep(1);}catch(Exception e1){} //让线程睡眠
System.out.println(Thread.currentThread().getName()+"is selling ticket"+ticket--);
}
}
}
}
*即4个窗口卖100张票*/
class NewThread
{
public static void main(String [] args)
{
TestThread tt=new TestThread(); //创建了4个线程,模拟4个售票窗口
Thread t1=new Thread(tt);
Thread t2=new Thread(tt);
Thread t3=new Thread(tt);
Thread t4=new Thread(tt);
t1.start();
t2.start();
t3.start();
t4.start();
}
}class TestThread implements Runnable
{
int ticket=100; //共同出售100张票
public void run()
{
sale();
}
public synchronized void sale() //定义同步方法
{
while(true)
{
if(ticket>0)
{
try{Thread.sleep(1);}catch(Exception e1){} //让线程睡眠
System.out.println(Thread.currentThread().getName()+"is selling ticket"+ticket--);
}
}
}
}
package view;/**
* <p>Title: testLog</p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2006</p>
*
* <p>Company: </p>
*
* @author jy
* @version 1.0
*/
class NewThread {
public static void main(String[] args) {
TestThread tt = new TestThread(); //创建了4个线程,模拟4个售票窗口
Thread t1 = new Thread(tt);
Thread t2 = new Thread(tt);
Thread t3 = new Thread(tt);
Thread t4 = new Thread(tt);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class TestThread implements Runnable {
int ticket = 100; //共同出售100张票
boolean lock = false;
public void run() {
while (true) {
if (ticket > 0) {
sale();
}
try {
Thread.sleep(1);
//Thread.yield();
} catch (Exception e1) {} //让线程睡眠 } } public void sale() { //定义同步方法 System.out.println(Thread.currentThread().getName() +
"is selling ticket" + ticket--);
}
}
我的程序是让线程不断切换,模拟窗口不停的售票,售卖到第1张时停止售票。第一个线程不需要结束,让线程sleep是模拟当ticket==1时(卖最后一张票时),此时运行的线程睡眠,其他三个线程sleep的地方(已经进入if(ticket>0))重新启动,就会打印出票号0,-1,-2;使用同步是避免它打印出0,-1,-2。而且线程调用sleep是会交出锁的,这么分析下来交出锁以后其他线程应该就会进入同步代码中啊。
您回复的代码因为没使用线程同步可能会出现bug,sleep是为了模拟当cpu正好将线程切换时,程序可能出现的bug。您写的代码中sleep放到了sale()方法后面,所以等于没写,所以也就无法看到问题,如果您将sleep写道sale()方法前面,问题就会出现了。如:
class NewThread {
public static void main(String[] args) {
TestThread tt = new TestThread(); //创建了4个线程,模拟4个售票窗口
Thread t1 = new Thread(tt);
Thread t2 = new Thread(tt);
Thread t3 = new Thread(tt);
Thread t4 = new Thread(tt);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class TestThread implements Runnable {
int ticket = 100; //共同出售100张票
boolean lock = false;
public void run() {
while (true) {
if (ticket > 0) {
try {
Thread.sleep(1);
//Thread.yield();
} catch (Exception e1) {} //让线程睡眠,模拟线程同步的安全性问题
sale();
}
} } public void sale() { //定义同步方法 System.out.println(Thread.currentThread().getName() +
"is selling ticket" + ticket--);
}
}程序最后输出了0,-1,-2。
Thread t2=new Thread(new TestThread());
Thread t3=new Thread(new TestThread());
Thread t4=new Thread(new TestThread());
这样试试。
public class NewThread { /**
* @param args
*/
public static void main(String[] args) {
TestThread tt = new TestThread();// 创建了4个线程,模拟4个售票窗口
Thread t1 = new Thread(tt);
Thread t2 = new Thread(tt);
Thread t3 = new Thread(tt);
Thread t4 = new Thread(tt);
t1.start();
t2.start();
t3.start();
t4.start();
}}class TestThread implements Runnable {
static int ticket = 100;// 共同出售100张票 public void run() {
while (true) {
sale();
}
} public synchronized void sale()// 定义同步方法
{
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (Exception e1) {
} // 让线程睡眠
System.out.println(Thread.currentThread().getName()
+ "is selling ticket" + ticket--);
}
}}
这样写我知道没问题,我就是想问问为什么这样写没问题,而我那样写就会只执行一个线程?两段代码应该差不多的啊,区别紧紧是将while(true)写在函数类和将while(true)写在函数外,为什么运行效果会不同咧?
如果按您的意思写的话,那4个线程都会创造自己的100张票,变成了4个窗口各卖各的100张票,因此程序也就失去了意义。
zbo(大门)的代码中创建的4个线程使用的是4个TestThread类对象的锁,因此也达不到数据同步的效果,数据还是会输出0,-1,-2啊。
把楼主的代码sleep时间延长,也无济于事,说明问题不是sleep的时间太短,而是根本就不给其他线程机会,sleep再旧也没用:如果把楼主代码中的synchronized去掉就不会出现单独线程独占的问题了,但是又会出现楼主所说的负数问题。所以把while放在外面,区别就是每次只做-1的sell操作,而这个简单的元操作被synchronized起来,而不是整个的while都被synchronized。
是的,问题就出在sleep是不交出锁的(错怪了tygker兄),但while(true)写在函数外时,程序为何能正常运行呢?此时synchronized的函数sale()应该还是保留锁的,为什么其他线程可以调用此函数呢?