【问题标题】:Synchronization help in JavaJava中的同步帮助
【发布时间】:2010-02-07 05:52:53
【问题描述】:

看着http://download.eclipse.org/jetty/stable-7/xref/com/acme/ChatServlet.html,我似乎不明白为什么同步方法中需要有一个同步块,像这样:

private synchronized void chat(HttpServletRequest request,HttpServletResponse response,String username,String message)
throws IOException
{
    Map<String,Member> room=_rooms.get(request.getPathInfo());
    if (room!=null)
    {
        // Post chat to all members
        for (Member m:room.values())
        {
            synchronized (m)
            {
                m._queue.add(username); // from
                m._queue.add(message);  // chat

                // wakeup member if polling
                if (m._continuation!=null)
                {
                    m._continuation.resume();
                    m._continuation=null;
                }
            }
        }
    }

如果整个方法已经是线程安全的,为什么m 需要同步(再次?)?

感谢您提供任何见解。

【问题讨论】:

    标签: java jetty synchronized multithreading


    【解决方案1】:

    同步方法“chat(...)”在它的实例对象上同步,而 synchronized(m) 在“m”对象上同步 - 所以它们在两个不同的对象上同步。基本上,它确保其他一些 servlet 对象不会同时与同一个 Member 实例混淆。

    【讨论】:

    • 谢谢,我明白了,但出于好奇.. 为什么 _rooms 对象也不同步?
    • 可能是因为 _rooms 只被同一类中的其他同步方法修改,所以只要您在同步方法中访问它,您就可以确定没有其他人在其中添加或删除项目它。理想情况下,它将被定义为“私有”,因为现在它是包私有的,这意味着包中的任何其他类(或子类)都可以访问它。
    • 感谢您的评论,但我需要回到我原来的问题。为什么同步'm'是必要的?它仅用于已经同步的方法(很像 _rooms)。还是同步“m”只是一种预防措施?
    • 我不太熟悉这个类,甚至是它正在演示的 Jetty Continuations,但在我看来,我认为没有必要在两个 servlet 实例上同步(在方法级别)和成员对象。同步所有方法可能“更安全”,但当多个客户端同时访问 servlet 时,它也存在不必要的阻塞风险。我认为仅在“房间”和“成员”对象上同步(并将它们设为私有)会是更好的方法。
    • 出色的反应,正是我的想法。非常感谢您的澄清!
    【解决方案2】:

    当整个方法同步时,会在this 对象上获得锁。但是同步块只在当前正在迭代中使用的成员上获得锁。

    【讨论】:

      【解决方案3】:

      同步在不同的锁上。

      方法定义中的synchronized 关键字意味着在this 上同步的其他代码不能与该方法并行运行。

      synchronized(m) 范围意味着在 m 上同步的其他代码不能与循环并行运行。

      【讨论】:

        猜你喜欢
        • 2023-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-02
        • 2011-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多