我想知道java中的“同步”是如何工作的。
假设我模拟了一个由许多领域组成的棋盘游戏。我将字段实现为类(字段),将字符串实现为包含许多字段的类(Board)。 让我们进一步说我在Field中建模了一个方法moveTo(Player pl),让玩家移动到该字段。每个玩家都由一个帖子代表。
虽然所有线程都应该同时执行某些操作(例如滚动骰子),但一次只能有一个玩家移动。
我如何确保? 是否足以使方法moveTo(Player pl)同步?或者我是否需要在Board中使用级联方法来确保一次只有一个玩家移动? (或者有更好的解决方案)?
将其置于底线:
“同步”会锁定具有此方法的每个对象中的方法,还是仅在当前正在使用的对象中同步锁定方法?
如果是第二种情况:是否有一种简单的方法可以为每个实现此方法的对象锁定方法?
谢谢!!!
答案 0 :(得分:29)
我认为你想要的是以下内容:
class Field {
// instance of the board
private Board board;
public void moveTo(Player p){
synchronized (board) {
// move code goes here
}
}
}
这将使每个棋盘只有一个玩家一次移动。如果您在板上获得同步锁定,则一次只能有一个Field进入同步锁定。 (假设有一个董事会)
如果您只是写道:
public synchronized void moveTo(Player p){
你只能确保玩家不能一次移动到同一个战场。这是因为当在定义中使用synchronized写入方法时,它将锁定在对象级别。因此,Field的每个实例都将是它自己的锁定对象,因此,只要玩家没有移动到同一个Field,玩家仍然可以同时移动。
答案 1 :(得分:7)
synchronized锁定对象,而不是方法。 Java没有功能。
如果希望在所有对象上只调用一次方法,则可以锁定共享对象,例如类。
我建议你只需要一个线程来执行所有的移动/操作,这将显着简化代码。为什么它必须是多线程的?
答案 2 :(得分:1)
同步锁定对资源的访问。该资源可以是函数或对象(包括this
对象)。
如果没有具体的例子,我们无法给你具体的建议。
在你的例子中,如果玩家一次只能转1圈,为什么他们需要在自己的线程中呢?为什么他们需要同时掷骰子?
同步函数会锁定对该实例的该方法版本的调用(除非它是静态方法)。
And if the second is the case: is there an easy way to lock a function for every object that has this function implemented?
这似乎表明您的设计可以重新评估。您的对象的实例方法是否真的共享状态,以便它们需要彼此同步的方法?为什么呢?
答案 3 :(得分:1)
取决于它的使用位置。
如果在典型方法中使用,它会专门抓取相关对象的“锁定”对象。没有其他Thread可以处理该对象中的方法,如果它们需要对同一个Object的“lock”对象的独占访问权限(非同步方法不需要对锁定的独占访问)。
如果在静态方法中使用,它将专门抓取表示Class的Object的lock对象。没有其他Thread可以处理该Class对象中的方法,如果它们需要对同一Class对象的“lock”对象的独占访问(非同步方法不需要对锁的独占访问)。
如果与明确声明的对象一起使用,它将专门抓取显式声明的对象的锁定对象。同样,在此期间,没有其他线程可以专门获取该对象的锁定。
一旦你离开同步区块的范围,你放弃对锁定的独占保留。