“同步”究竟做了什么?锁定函数或锁定对象函数?

时间:2011-01-03 16:22:20

标签: java multithreading locking synchronized

我想知道java中的“同步”是如何工作的。

假设我模拟了一个由许多领域组成的棋盘游戏。我将字段实现为类(字段),将字符串实现为包含许多字段的类(Board)。 让我们进一步说我在Field中建模了一个方法moveTo(Player pl),让玩家移动到该字段。每个玩家都由一个帖子代表。

虽然所有线程都应该同时执行某些操作(例如滚动骰子),但一次只能有一个玩家移动。

我如何确保? 是否足以使方法moveTo(Player pl)同步?或者我是否需要在Board中使用级联方法来确保一次只有一个玩家移动? (或者有更好的解决方案)?

将其置于底线:
“同步”会锁定具有此方法的每个对象中的方法,还是仅在当前正在使用的对象中同步锁定方法?
如果是第二种情况:是否有一种简单的方法可以为每个实现此方法的对象锁定方法?

谢谢!!!

4 个答案:

答案 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”对象的独占访问(非同步方法不需要对锁的独占访问)。

如果与明确声明的对象一起使用,它将专门抓取显式声明的对象的锁定对象。同样,在此期间,没有其他线程可以专门获取该对象的锁定。

一旦你离开同步区块的范围,你放弃对锁定的独占保留。