【问题标题】:Why the synchronized method can be called by only two threads in turn?为什么同步方法只能被两个线程依次调用?
【发布时间】:2019-05-09 14:06:08
【问题描述】:

我在课堂上有一个同步方法。 try 子句中的代码调用notifyAll()wait()。当我运行代码时,所有线程都根据输出运行。但事实证明只有两个线程依次调用该方法。太可怕了。

我尝试在非同步方法的 while 循环中编写同步块,并且效果很好。请注意,总共有 5 个线程。

这里是同步方法:

private synchronized void sell() {
        while (ticketsLeft > 0) {
            try {
                    System.out.println(Thread.currentThread().getName() + "__________" + (ticketsLeft--));
                    this.notifyAll();
                    Thread.sleep(10);
                    this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.exit(0);
    }

我也尝试将while循环放在同步块中,同样的事情发生了。

private void sell() {
        synchronized (this) {
            while (ticketsLeft > 0) {
                try {
                    System.out.println(Thread.currentThread().getName() + "__________" + (ticketsLeft--));
                    this.notifyAll();
                    Thread.sleep(10);
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.exit(0);
        }
    }

而且是这样工作的,线程 3 和 4 依次调用该方法:

5__________100
1__________99
2__________98
3__________97
4__________96
3__________95
4__________94
3__________93
4__________92
3__________91
4__________90
3__________89
4__________88
3__________87
4__________86
3__________85
4__________84
3__________83
4__________82
3__________81
4__________80

在非同步方法内的while循环中使用同步块:

    private void sell() {
        while (ticketsLeft > 0) {
            try {
                synchronized (this) {
                    System.out.println(Thread.currentThread().getName() + "__________" + (ticketsLeft--));
                    this.notifyAll();
                    Thread.sleep(10);
                    this.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.exit(0);
    }

它按我的预期工作:

5__________100
3__________99
2__________98
1__________97
4__________96
1__________95
2__________94
3__________93
1__________92
4__________91
3__________90
2__________89
5__________88
2__________87
3__________86
4__________85
1__________84
3__________83
2__________82
5__________81
3__________80

感谢大家阅读这个问题。很抱歉,我没有足够的声誉来发布图片。如果有人对此有想法,我将不胜感激。

【问题讨论】:

  • 因为任何线程碰巧在它们都被唤醒后首先尝试获取同步锁都会获得同步锁,并且很有可能根据您的特定配置,它是前两个。如果您希望资源与所有线程公平共享,请使用一种公平平衡的机制。这根本不是同步的重点,相反,同步试图成为最有效的,远非最公平的。

标签: java multithreading synchronized


【解决方案1】:

这里没有足够的信息来正确回答这个问题。但我认为这与第二种情况下的while循环在同步块之外有关,它首先是在同步方法内的while循环。

在第二种方法中,所有线程将在while循环内等待,但对于第一种方法,它们将在while循环外等待。

注意:同步方法和同步方法都锁定了线程正在运行的类的当前实例。

希望这会有所帮助!! :-)

【讨论】:

  • 首先感谢您帮助我,完整的课程文件可以在这里找到:gist
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多