Java 它';始终使用';这';作为监视器锁?
例如,我有一个具有2个计数器的类(在多线程环境中): 有两个增量操作彼此不相关。但我对锁使用相同的对象(Java 它';始终使用';这';作为监视器锁?,java,multithreading,Java,Multithreading,例如,我有一个具有2个计数器的类(在多线程环境中): 有两个增量操作彼此不相关。但我对锁使用相同的对象(this) 确实,如果客户端同时调用increment1()和increment2()方法,那么increment2调用将被阻止,直到increment1()释放this监视器为止 如果这是真的,是否意味着我需要为每个操作提供不同的监视器锁(出于性能原因) 如果在方法上进行同步,就像在这里所做的那样,锁定整个对象,因此两个线程访问来自同一对象的不同变量时,无论如何都会相互阻塞 如果您想一次只同
this
)
确实,如果客户端同时调用increment1()
和increment2()
方法,那么increment2
调用将被阻止,直到increment1()
释放this
监视器为止
如果这是真的,是否意味着我需要为每个操作提供不同的监视器锁(出于性能原因) 如果在方法上进行同步,就像在这里所做的那样,锁定整个对象,因此两个线程访问来自同一对象的不同变量时,无论如何都会相互阻塞
如果您想一次只同步一个计数器,这样两个线程在访问不同变量时不会互相阻塞,那么您必须将这两个计数器添加到两个同步块中,并使用不同的变量作为两个块的“锁” 如果您需要能够并行调用两个操作所带来的性能优势,那么是的,您不需要为不同的操作提供不同的监视对象 然而,对于过早的优化有一些话要说,在使程序变得更复杂以适应它之前,您应该确保您需要它 确实,如果客户端同时调用increment1()和increment2()方法,则在increment1()释放此监视器之前,increment2调用将被阻止 如果在同一实例上调用它们,则是 如果这是真的,是否意味着我需要为每个操作提供不同的监视器锁(出于性能原因) 只有你知道。我们不知道您的性能要求。这实际上是您的真实代码中的一个问题吗?你的实际行动是否持久?它们经常发生吗?您是否执行过任何诊断来评估此问题的影响?您是否分析过您的应用程序,以了解等待监视器所花费的时间,更不用说不必要的时间了 实际上,出于完全不同的原因,我建议不要在
上进行同步。当你控制一切的时候,就已经很难对线程进行推理了——但是当你不知道可以获得监视器的所有东西的时候,你就处于一种无所事事的状态。当您在上同步此
时,这意味着对您的对象具有引用的任何其他代码也可以在同一监视器上同步。例如,客户机可以使用:
synchronized (myClass) {
// Do something entirely different
}
这可能导致死锁、性能问题,以及各种各样的问题
如果您在类中使用一个私有final
字段,而创建的对象只是一个监视器,那么您知道获取该监视器的唯一代码将是您的代码。是如果多个线程尝试调用对象上的方法,它们将等待尝试获取锁(虽然谁获得锁的顺序不能保证。)正如所有事情一样,在您知道这是代码中的瓶颈之前,没有理由进行优化。您是对的,如果您使用相同的对象,这将是一个性能瓶颈。您可以对单个计数器使用不同的锁,也可以对并发计数器使用java.util.concurrent.atomic.AtomicInteger
比如:
是,给定代码与以下代码相同:
public void increment1() {
synchronized(this) {
counter1++;
}
}
public oid increment2() {
synchronized(this) {
counter2++;
}
}
这意味着同一时间只能执行一个方法。您应该提供不同的锁(并且在这个上锁定是一个坏主意),或者使用其他解决方案。第二个是您实际需要的解决方案:1)是的,递增1()确实会阻止递增2()反之亦然,因为它们都在上隐式同步此
2)如果需要更好的性能,请考虑无锁JavaUTI.CONCURNET.AIMICIC.ActudioType类
private AtomicInteger counter1 = new AtomicInteger();
private AtomicInteger counter2 = new AtomicInteger();
public void increment1() {
counter1.getAndIncrement();
}
public void increment2() {
counter2.getAndIncrement();
}
@这是完全错误的。OP正确。@dinesh707只有在JVM确定它们不交互时才正确。如果它们确实进行交互,则必须同步。我将其取下,因为它添加了错误的值您锁定了整个对象-这意味着如果我调用长同步方法ob object,则在同步方法停止运行之前,我无法使用此对象?您可以使用此对象,但不能将此对象作为锁定执行监视输入!因此,对increment2的另一次调用(也需要锁定“this”对象)将不得不等待。
public void increment1() {
synchronized(this) {
counter1++;
}
}
public oid increment2() {
synchronized(this) {
counter2++;
}
}
private AtomicInteger counter1 = new AtomicInteger();
private AtomicInteger counter2 = new AtomicInteger();
public void increment1() {
counter1.getAndIncrement();
}
public void increment2() {
counter2.getAndIncrement();
}