2012-01-08 45 views
3

我有一个多线程应用程序(Tomcat中的Web应用程序)。其中有一个类几乎每个线程都有自己的实例。在那个类中,有一段代码只有一个线程(用户)可以一次执行。我的研究使我相信,我在这里需要的是一个互斥体(它是一个计数为1的信号量,看起来)。在Java中实现互斥体

因此,经过多一点研究,我认为我应该做的是以下几点。重要的是要注意我的锁对象是静态的。

我做得对吗?

public Class MyClass { 
    private static Object lock = new Object(); 
    public void myMethod() { 
    // Stuff that multiple threads can execute simultaneously. 
    synchronized(MyClass.lock) { 
     // Stuff that only one thread may execute at a time. 
    } 
    } 
} 
+2

没理由不工作。你也可以使用'ReentrantLock'来达到同样的效果。 – fge 2012-01-08 14:32:27

回答

5

在你的代码,myMethod可以在任何线程中执行,但只有一次一个。这意味着永远不会有两个线程同时执行此方法。我认为这就是你想要的 - 所以:是的。

+0

谢谢!线程将“排队”等待锁定?如果他们无法获得锁,他们不会立即失败? – 2012-01-08 14:37:35

+1

是的,他们会等。如果该方法永不返回,他们甚至可能无休止地冻结应用程序。 – Yogu 2012-01-08 14:39:29

+1

为了避免挂起,你可能想看看期货模式/框架,或者有其他形式的回调系统。这将允许那些等待“在等待时买票并做其他事情”的人。 – 2012-01-08 14:41:57

2

通常,多线程问题来自可变性 - 其中两个或多个线程正在访问相同的数据结构,其中一个或多个线程修改它。

第一本能就是使用锁来控制访问顺序,正如你所建议的那样 - 然而,当你的线程驻留在锁定监视器上时,你的应用程序可能会很快进入锁定争用的地方, 。

通过转移到不可变的数据结构,您可以摆脱大部分问题 - 因此您可以从setter中返回一个新对象,而不是修改现有对象,也可以使用并发集合,如ConcurrentHashMap/CopyOnWriteArrayList。

并发编程是您需要掌握的东西,特别是吞吐量来自今天现代计算机世界中的并行处理。

+0

谢谢。在这种情况下,它不是我保护的数据,而是访问一次只允许一个“用户”的外部硬件资源。我同意,并发编程是必不可少的,我计划在那里提高我的技能。 – 2012-01-08 14:40:05

+0

有效的点 - 虽然我仍然会对这种瓶颈可能对系统造成的影响持谨慎态度。我花了大部分时间调整高负载/吞吐量应用程序,尽管 – 2012-01-08 14:43:10

1

这将允许一次一个线程通过该块。其他线程会等待,但是没有队列,因此不能保证线程以公平的方式获得锁定。事实上,与偏向锁,它不太公平。 ;)

你的锁应该是final如果有任何理由,它可能不是它可能是一个错误。顺便说一句:你可能可以用synchronized(MyClass.class)代替。

+0

“MyClass.class”可用于其他类,因此也是一个可能的错误源。 – Yogu 2012-01-08 14:47:41

+0

谢谢。在这种情况下,我认为不公平。该应用程序使用非常少,而且它们是一个受控观众(即没有其他应用程序与我的竞争对手)。 – 2012-01-08 14:50:50