Java 是否可以同步数据成员而不同步方法?
在阅读了这里关于Java同步方法的主题之后,我尝试在我的多人游戏中实现它,因为许多线程被打开并试图访问相同的资源。 我已经使方法同步,但这对我没有帮助,因为如果我有一个名为ArrayList clientConnection的数据成员;可用的方法有:Java 是否可以同步数据成员而不同步方法?,java,Java,在阅读了这里关于Java同步方法的主题之后,我尝试在我的多人游戏中实现它,因为许多线程被打开并试图访问相同的资源。 我已经使方法同步,但这对我没有帮助,因为如果我有一个名为ArrayList clientConnection的数据成员;可用的方法有: int getArrayListSize() { clientConnection.size(); } void addConnection(ServerConnection i_connection) { clientConne
int getArrayListSize() {
clientConnection.size();
}
void addConnection(ServerConnection i_connection) {
clientConnection.add(i_connection);
}
void removeConnection(ServerConnection i_connection) {
int index = clientConnections.indexOf(i_Connection);
clientConnections.remove(index);
}
ServerConnection getClientFromArrayListByIndex(int i_Index) {
ServerConnection client = this.clientConnections.get(i_Index);
}
我试着创建一个全局同步方法,以便在需要使用其中一个方法时传入操作类型和其他数据,并锁定函数。
问题是有两个函数返回void,一个返回int,一个返回ServerConnection,所以我不能创建这个全局方法。
我的问题是,是否有可能在Java中锁定数据成员而不是方法,以便锁定clientConnection数据成员?
谢谢。您可以使用
synchronized
关键字同步函数。例如:
synchronized ServerConnection getClientFromArrayListByIndex(int i_Index) {
ServerConnection client = this.clientConnections.get(i_Index);
// ...
}
如果你有一个类,你可以简单地在你的方法前面加上
synchronized
;那么在这些方法中只有一个线程。但是如果你真的需要这个,请想一想;这可能会减慢执行速度。如果有公共字段,则应将其设置为私有并创建getter方法。如果同步所有这些方法,则一次只有一个线程能够调用任何方法,因此,只要这些方法能够访问列表,列表将以线程安全的方式访问(即列表是私有的,没有其他方法使用该列表)
您可以使用将您的列表
打包为一个,所有的方法都是同步的
这是否比同步类中的方法更好,取决于方法的其他功能,以及这些功能是否需要协调。我的问题是,一个线程可以从clientConnection arrayList中删除服务器连接,同时另一个线程尝试获取arrayList大小或获取e指定索引中已删除但未确定的serverconnection对象。那么您应该手动指定锁定对象。您可以基于
clientConnection
ArrayList进行同步,一次只能有一个线程访问该对象。一般的经验法则是在共享的资源上同步(以及潜在问题的原因)。您也可以研究使用conncurrent数据结构。此方案可能会导致ArrayIndexOutOfBoundsException,但不会因为并发问题而使列表处于不确定状态。只需正确记录该方法,和/或在索引不再有效时使其返回null,和/或引发自定义异常,而不是如果索引不再有效,则默认的ArrayIndexOutOfBoundsException。你说我可以锁定arraylist吗?是的,只需将对arraylist的访问包装到synchronized(clientConnections){…}但是,正如其他人在这个答案中提到的和其他的一样,你也需要考虑性能。理想情况下,如果共享资源存在争用,你希望发生什么?例如,你可以使用一个阻塞队列,它基本上只是排队操作。,然后读取,读取操作将需要等待删除完成。但是,有些客户端可能会被困在等待中。在游戏中,这真的很糟糕。这是一个老生常谈;你不应该让所有类的所有方法都同步。你应该考虑一下。但我认为正确也比快速好。让所有方法都同步如果在同一个arraylist上有不同类型的操作,例如:add、remove、getsize等,我该怎么办?如果我有3个线程,每个线程在同一时间使用不同的方法,这可能会导致一个大问题。你可以使用synchronizedList或在arraylist上进行同步。这听起来像是great solution,您有使用示例吗?removeConnection()方法除外,该方法可能会失败-它执行两个操作,每个调用都会同步,但不是原子单元(并且需要)。另一个线程可能会修改indexOf()和remove()之间的列表调用。我没有发现在removeConnection()
中发生了什么-给定那里的代码,这将创建一个竞争条件,因此是不合适的。我确实提到了这是否合适取决于方法中发生的其他事情,但是…@ToddremoveConnection(…)
可以简单地重写为使用List#remove(Object o)
,在这种情况下这不会是一个问题。更不用说getClientFromArrayListByIndex(…)
调用对任何基于列表的实现都会带来一些重大的锁定挑战。在我看来,getArrayListSize
和getClientFromArrayListByIndex
不属于您对象的公共接口。如果您能告诉我们实际使用情况,我们可以将您引导到正确的方向。问题出在哪里因此,我需要更多可以访问列表的方法,比如删除连接或迭代查找连接……同时同步这些方法。
synchronized int getArrayListSize() { ... }
synchronized void addConnection(ServerConnection i_connection) { ... }
etc.