繁体   English   中英

如何同步两个方法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM