Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否可以同步数据成员而不同步方法?_Java - Fatal编程技术网

Java 是否可以同步数据成员而不同步方法?

Java 是否可以同步数据成员而不同步方法?,java,Java,在阅读了这里关于Java同步方法的主题之后,我尝试在我的多人游戏中实现它,因为许多线程被打开并试图访问相同的资源。 我已经使方法同步,但这对我没有帮助,因为如果我有一个名为ArrayList clientConnection的数据成员;可用的方法有: int getArrayListSize() { clientConnection.size(); } void addConnection(ServerConnection i_connection) { clientConne

在阅读了这里关于Java同步方法的主题之后,我尝试在我的多人游戏中实现它,因为许多线程被打开并试图访问相同的资源。 我已经使方法同步,但这对我没有帮助,因为如果我有一个名为ArrayList clientConnection的数据成员;可用的方法有:

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()
中发生了什么-给定那里的代码,这将创建一个竞争条件,因此是不合适的。我确实提到了这是否合适取决于方法中发生的其他事情,但是…@Todd
removeConnection(…)
可以简单地重写为使用
List#remove(Object o)
,在这种情况下这不会是一个问题。更不用说
getClientFromArrayListByIndex(…)
调用对任何基于列表的实现都会带来一些重大的锁定挑战。在我看来,
getArrayListSize
getClientFromArrayListByIndex
不属于您对象的公共接口。如果您能告诉我们实际使用情况,我们可以将您引导到正确的方向。问题出在哪里因此,我需要更多可以访问列表的方法,比如删除连接或迭代查找连接……同时同步这些方法。
synchronized int getArrayListSize() { ... }
synchronized void addConnection(ServerConnection i_connection) { ... }
etc.