Java多线程售票示例异常:仅单个线程执行售票逻辑求助
Java多线程售票示例仅单个线程执行的问题解决
我编写了一个Java多线程售票示例,但运行后发现只有单个线程完成了全部售票操作。
原代码
public class test2 { public static void main(String[] args) { per per = new per(); Thread t1 = new Thread(per); Thread t2 = new Thread(per); Thread t3 = new Thread(per); t1.start(); t2.start(); t3.start(); } } class per implements Runnable { int ticket = 10; final String a = ""; @Override public void run() { while (true) { synchronized(a) { if (ticket > 0) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " ticket " + ticket); ticket--; } } } } }
实际运行结果
Thread-1 ticket 9 Thread-1 ticket 8 Thread-1 ticket 7 Thread-1 ticket 6 Thread-1 ticket 5 Thread-1 ticket 4 Thread-1 ticket 3 Thread-1 ticket 2 Thread-1 ticket 1 Thread-1 ticket 0
问题原因
- 锁对象不合理:用空字符串
""作为锁对象,虽然是final修饰,但空字符串属于Java常量池全局共享实例,锁的语义不清晰,还可能引发意外的锁冲突。 - 线程调度偏向:线程释放锁后会立刻进入下一轮
while循环抢锁,操作系统调度可能优先让刚释放锁的线程再次获取锁,导致其他线程抢锁机会被压制。 - 无循环退出逻辑:票售罄后线程仍会无限循环尝试抢锁,完全是无效的资源消耗。
修复后的代码
public class TicketSaleTest { public static void main(String[] args) { TicketSeller seller = new TicketSeller(); Thread t1 = new Thread(seller, "售票窗口1"); Thread t2 = new Thread(seller, "售票窗口2"); Thread t3 = new Thread(seller, "售票窗口3"); t1.start(); t2.start(); t3.start(); } } class TicketSeller implements Runnable { private int ticket = 10; @Override public void run() { while (true) { // 用当前共享的Runnable实例作为锁,语义明确且安全 synchronized (this) { if (ticket <= 0) { // 票卖完直接退出循环,停止抢锁 break; } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 售出第 " + ticket + " 张票"); ticket--; } // 主动让步,给其他线程抢锁机会,让多线程效果更明显 Thread.yield(); } } }
修复要点
- 替换锁对象为
this,利用共享的Runnable实例作为锁,避免常量池锁的潜在问题。 - 添加
ticket <= 0的退出条件,终止无效的循环抢锁行为。 - 在同步块结束后调用
Thread.yield(),主动让当前线程放弃CPU执行权,提升其他线程抢锁的概率,保证多线程售票的效果。
内容的提问来源于stack exchange,提问作者Sihan Adi
相关产品推荐
相关产品推荐

