Java,为什么需要使用同步?而不是使用单个线程?

时间:2017-08-01 09:21:21

标签: java

在阅读Java同步时,我只是想知道,如果处理应该是同步的,为什么不只是创建一个线程(而不是主线程)并逐个处理而不是创建多个线程。

因为,通过'synchronized',除了单个运行的线程之外,所有其他线程将只是等待。似乎唯一的单线程正在运作。

请告诉我我错过了什么。

如果您能提供一些用例,我将非常感激。

我读了一个例子,关于从2台ATM设备访问银行账户的例子。但它让我更加困惑,阻塞(Lock)应该由数据库端完成,我想。我认为'synchronized'在多个EC2实例之间不起作用。

如果我的想法错了,请修理我。

3 个答案:

答案 0 :(得分:2)

如果您使用多个线程运行的所有代码都在synchronized块内,那么使用单个线程确实没有区别。

然而,一般来说,您的代码包含可以并行运行在多个线程上的部分和不能运行的部分。后者需要同步而不是前者。通过使用多个线程,您可以加速" parallelisable"位。

答案 1 :(得分:1)

你可以有一个单独的线程并逐个处理(这已经完成),但这样做会产生相当大的开销,并且不会消除同步的需要。

您处于多线程开始的情况下(例如,您有许多同时进行的Web会话)。你想在一个线程中完成一部分处理 - 让我们说用一些新数据更新一些常见的结构。您需要将新数据传递给单个线程 - 您如何获得它?您将不得不使用某种消息队列(或同等的东西)并让单线程从消息队列中挑选请求,并且无论如何都必须进行同步,此外还有管理队列的开销以及问题您需要异步从单个线程获得回复。所以你回到原点。

此技术适用于您需要处理的工作量相当大并且您不想长时间阻止主线程的情况。

总结:拥有一个线程不会消除同步的需要。

答案 2 :(得分:1)

让我们考虑以下用例:

您的应用程序是一款互联网浏览器游戏。每个玩家都有一个分数,可以点击一个按钮。每次玩家点击按钮时,他们的分数会增加,而他们的对手会减少。第一个达到10胜的玩家。

根据游戏的性质,并且要单独获得一个独特的赢家,你必须原则上考虑两个计数器的增加(以及对获胜者的检查)。

你将让每个玩家在他们自己的线程上发送clickEvents,每个事件都会转换为所有者计数器的增加,检查计数器是否达到10以及对手的计数器减少。

这很容易通过同步处理修改计数器的方法来完成:每个并发线程都会尝试获取锁,当它们执行时,它们将执行代码(最后释放锁)。

锁定机制非常轻量级,只需要一个代码关键字。

如果我们按照您的建议实现另一个将处理执行的线程,我们必须实现整个线程管理逻辑(更多代码),初始化该线程(更多资源),甚至如此,以保证公平性处理事件时,您仍然需要一种方法让客户端线程将事件传递给执行程序线程。我认为这样做的唯一方法是实现一个BlockingQueue,它也是同步的,以防止在尝试从另外两个线程添加元素时自然发生的竞争条件。

我真的没有找到一种方法来解决这个非常简单的用例而没有同步(或者实现你自己的锁定算法基本上做同样的事情)。