我知道当你想要锁定方法只能由一个线程执行时,你用synchronized
关键字声明它。
类如何在线程时如何提供对整个类对象的锁定 正在该类的实例上执行一些代码?
换句话说,当一个线程正在对象上执行一个方法时,不应该有其他线程 即使在同一个类的不同实例上也允许执行相同的方法。
答案 0 :(得分:8)
您在特定对象上同步,可以是某个指定的静态锁定对象,也可以是类对象(当声明静态方法被同步时会发生这种情况):
class X {
private static final Object lock = new Object();
public void oneAtATime() {
synchronized (lock) {
// Do stuff
}
}
}
class Y {
public void oneAtATime() {
synchronized (Y.class) {
// Do stuff
}
}
}
每个变体都有自己的优点和缺点;锁定类允许类之外的其他代码出于其自身原因使用相同的锁(这允许它协调比您提供的更高级别的同步),而static final Object lock
方法允许您禁止它通过使锁定字段为私有(这使得更容易推断锁定并避免代码死锁,因为其他人编写了错误的代码)。
你当然也可以使用java.util.concurrent
中的一些同步机制,比如显式Lock
,它提供了对锁定的更多控制(而ReentrantLock
目前比隐式锁更好地执行高争议)。
编辑:请注意,静态/全局锁定不是一个好方法 - 它意味着所创建的类的每个实例都将基本上绑定到每个其他实例(除了制作之外)它更难测试或读取代码,严重损害可扩展性)。我假设你这样做是为了同步某种全局状态?在这种情况下,我会考虑在类中包装全局/静态状态,并实现每个实例的同步而不是全局。
而不是像这样:
class Z {
private static int state;
public void oneAtATime(){
synchronized (Z.class) {
state++;
}
}
}
这样做:
class State {
private int value;
public synchronized void mutate(){ value++; }
}
class Z {
private final State state;
public Z(State state){
this.state = state;
}
public void oneAtATime(){
state.mutate();
}
}
// Usage:
State s1 = new State(), s2 = new State();
Z foo = new Z(s1);
Z bar = new Z(s1);
Z frob = new Z(s2);
Z quux = new Z(s2);
现在foo
和bar
仍然相互关联,但它们可以独立于frob
和quux
工作。
答案 1 :(得分:5)
如果使用静态同步方法,则会通过类锁定锁定它们。您还可以在类中声明一个静态Object,并在我认为的方法中将其锁定:
private static final Object STATIC_LOCK = new Object();
private void foo() {
synchronized (STATIC_LOCK) {
//do stuff...
}
}
答案 2 :(得分:2)
您可以在该方法中使用静态Mutex
。所以任何并发线程都在方法内阻塞,而另一个并发运行它,无论它属于哪个类的对象。我认为没有任何特殊的单一关键字可以产生与synchronized
相同的效果。
这是一个相当激进的同步,我会尽可能地避免它。
答案 3 :(得分:2)
在类的静态字段或类本身上同步:
synchronized(MyClass.class) {
// mutually excluded method body
}
答案 4 :(得分:1)
两个线程都必须使用此构造
public void someMethod() {
synchronized(ClassThatShouldBeProtected.class) {
someSynchronizedCode();
}
}
这种方法得益于这样一个事实,即类本身就是一个对象,因此它有一个监视器。然后你不需要任何人工静态实例。
答案 5 :(得分:0)
没有内置机制。创建自己的静态锁属性,并确保锁定它并在每种方法中解锁它。不要忘记例外 - 确保在“最后”部分解锁它。
答案 6 :(得分:0)
这应该有效:
public class MyClass {
void synchronizedMethod() {
synchronized (MyClass.class) {
// synchronized on static level
}
}
}
哪个'错过'类的锁定运行时表示。这是可能的,因为任何对象都可以用作Java中的互斥锁。
答案 7 :(得分:0)
http://www.janeg.ca/scjp/threads/synchronization.html
谈到实现它的几种方法。 通常,锁是禁止的并且阻碍了线程的好处。因此,关键代码应尽量减少。
你想要一个类杠杆锁来访问该类的静态变量,还是要保护对该类的公共外部资源的访问?在这种情况下,您应该在访问它时有一个单独的锁。