[英]How to synchronize two methods
我在 Java 中有以下用于聊天服务器应用程序的代码 -
public synchronized List<ChatMessage> getMessages(int messageNumber) {
return messages.subList(messageNumber + 1, messages.size());
}
public synchronized int addMessage(ChatMessage c) {
messages.add(c);
return messages.size()-1;
}
我有以下测试代码 -
public static void main(String[] args) {
final ChatRoom c = new ChatRoom();
Thread user1 = new Thread(new Runnable() {
public void run() {
for(int i=0;i<1000;i++) {
c.addMessage(new ChatMessage());
c.getMessages(0);
}
}
});
Thread user2 = new Thread(new Runnable() {
public void run() {
for(int i=0;i<1000;i++) {
c.addMessage(new ChatMessage());
c.getMessages(0).size();
}
}
});
user1.start();
user2.start();
}
我收到了 ConcurrentModificationException。
这怎么可能?
这怎么可能?
您的getMessages
方法只返回原始列表中的一个视图。 它不会创建列表的副本。 因此,一个线程正在使用列表中的一个视图,而另一个线程正在修改列表——此时,您会得到异常。
从List.subList
的文档中:
如果支持列表(即此列表)以除通过返回列表以外的任何方式在结构上进行了修改,则此方法返回的列表的语义将变得未定义。 (结构修改是指那些改变此列表大小的修改,或者以其他方式扰乱它,以至于正在进行的迭代可能会产生不正确的结果。)
目前尚不清楚您在这里真正想要实现的目标是什么,但从根本上说,您不能使用subList
神奇地创建线程安全列表:)
最简单的做法是创建一个组合方法
public synchronized int addMessageAndGetCount(ChatMessage c) {
messages.add(c);
return messages.size();
}
public static void main(String... args) {
final ChatRoom c = new ChatRoom();
final Runnable runner = new Runnable() {
public void run() {
for(int i = 0; i < 1000; i++) {
c.addMessageAndGetCount(new ChatMessage());
}
}
};
new Thread(runner).start();
new Thread(runner).start();
}
您不能从同步块中安全地返回列表或子列表。 您可以退还副本,但您只需要尺寸即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.