在lockObject上同步和使用this作为锁有什么区别?

发布于 2024-09-12 06:33:19 字数 514 浏览 1 评论 0原文

我知道同步方法和同步块之间的区别,但我不确定同步块部分。

假设我有这段代码

class Test {
  private int x=0;
  private Object lockObject = new Object();

  public void incBlock() {
    synchronized(lockObject) {
      x++;
    }
    System.out.println("x="+x);
  }

  public void incThis() {  // same as synchronized method
    synchronized(this) {
      x++;
    }
    System.out.println("x="+x);
  }
}

在这种情况下使用 lockObject 和使用 this 作为锁有什么区别?这对我来说似乎是一样的。

当你决定使用同步块时,你如何决定哪个对象是锁?

I know the difference between synchronized method and synchronized block but I am not sure about the synchronized block part.

Assuming I have this code

class Test {
  private int x=0;
  private Object lockObject = new Object();

  public void incBlock() {
    synchronized(lockObject) {
      x++;
    }
    System.out.println("x="+x);
  }

  public void incThis() {  // same as synchronized method
    synchronized(this) {
      x++;
    }
    System.out.println("x="+x);
  }
}

In this case what is the difference between using lockObject and using this as the lock? It seems to be the same to me..

When you decide to use synchronized block, how do you decide which object to be the lock?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

浮光之海 2024-09-19 06:33:19

就我个人而言,我几乎从不锁定“这个”。我通常锁定一个私人持有的引用,我知道没有其他代码会锁定该引用。如果您锁定“this”,那么了解您的对象的任何其他代码都可能会选择锁定它。虽然这种情况不太可能发生,但它肯定会发生——并且可能导致死锁,或者只是过度锁定。

你锁定的东西并没有什么特别神奇的地方——你可以有效地将它视为一个令牌。任何使用相同令牌锁定的人都会尝试获取相同的锁。除非您希望其他代码能够获取相同的锁,否则请使用私有变量。我鼓励您将变量final - 我不记得我曾经曾经想要换锁的情况对象生命周期内的变量。

Personally I almost never lock on "this". I usually lock on a privately held reference which I know that no other code is going to lock on. If you lock on "this" then any other code which knows about your object might choose to lock on it. While it's unlikely to happen, it certainly could do - and could cause deadlocks, or just excessive locking.

There's nothing particularly magical about what you lock on - you can think of it as a token, effectively. Anyone locking with the same token will be trying to acquire the same lock. Unless you want other code to be able to acquire the same lock, use a private variable. I'd also encourage you to make the variable final - I can't remember a situation where I've ever wanted to change a lock variable over the lifetime of an object.

谁把谁当真 2024-09-19 06:33:19

当我阅读《Java 并发实践》时,我也遇到了同样的问题,我想我应该对 Jon Skeet 和 spullara 提供的答案添加一些补充观点。

下面是一些示例代码,当 doStuff(ValueHolder) 方法执行时,它们甚至会阻塞“快速”的 setValue(int)/getValue() 方法。

public class ValueHolder {
    private int value = 0;

    public synchronized void setValue(int v) {
        // Or could use a sychronized(this) block...
        this.value = 0;
    }

    public synchronized int getValue() {
        return this.value;
    }
}

public class MaliciousClass {

    public void doStuff(ValueHolder holder) {
        synchronized(holder) {
            // Do something "expensive" so setter/getter calls are blocked
        }
    }
}

使用 this 进行同步的缺点是其他类可以在对您的类的引用上进行同步(当然不是通过 this)。在锁定对象引用时恶意或无意地使用 synchronized 关键字可能会导致您的类在并发使用下表现不佳,因为外部类可以有效地阻止您的 this-synchronized方法,并且您无法(在您的类中)执行任何操作来在运行时禁止这种情况。为了避免这种潜在的陷阱,您可以在私有最终对象上进行同步,或者使用java.util.concurrent.locks中的Lock接口。

对于这个简单的示例,您可以交替使用 AtomicInteger 而不是同步 setter/getter。

I had this same question when I was reading Java Concurrency In Practice, and I thought I'd add some added perspective on the answers provided by Jon Skeet and spullara.

Here's some example code which will block even the "quick" setValue(int)/getValue() methods while the doStuff(ValueHolder) method executes.

public class ValueHolder {
    private int value = 0;

    public synchronized void setValue(int v) {
        // Or could use a sychronized(this) block...
        this.value = 0;
    }

    public synchronized int getValue() {
        return this.value;
    }
}

public class MaliciousClass {

    public void doStuff(ValueHolder holder) {
        synchronized(holder) {
            // Do something "expensive" so setter/getter calls are blocked
        }
    }
}

The downside of using this for synchronization is other classes can synchronize on a reference to your class (not via this, of course). Malicious or unintentional use of the synchronized keyword while locking on your object's reference can cause your class to behave poorly under concurrent usage, as an external class can effectively block your this-synchronized methods and there is nothing you can do (in your class) to prohibit this at runtime. To avoid this potential pitfall, you would synchronize on a private final Object or use the Lock interface in java.util.concurrent.locks.

For this simple example, you could alternately use an AtomicInteger rather than synchronizing the setter/getter.

女中豪杰 2024-09-19 06:33:19

Effective Java Second Edition 的第 67 项是避免过度同步,因此我会在私有锁对象上同步。

Item 67 of Effective Java Second Edition is Avoid excessive synchronization, thus I would synchronize on a private lock object.

旧城烟雨 2024-09-19 06:33:19

Java 中的每个对象都可以充当监视器。选择一种取决于您想要的粒度。选择“this”的优点和缺点是其他类也可以在同一监视器上同步。不过,我的建议是避免直接使用 Synchronize 关键字,而是使用 java.util.concurrency 库中的结构,这些结构更高级别并且具有明确定义的语义。这本书中有很多来自著名专家的好建议:

Java Concurrency in Practice
http://amzn.com/0321349601

Every object in Java can act as a monitor. Choosing one is dependent on what granularity you want. Choosing 'this' has the advantage and disadvantage that other classes could also synchronize on the same monitor. My advice though is to avoid using the synchronize keyword directly and instead use constructs from the java.util.concurrency library which are higher level and have well defined semantics. This book has a lot of great advice in it from very notable experts:

Java Concurrency in Practice
http://amzn.com/0321349601

海螺姑娘 2024-09-19 06:33:19

在这种情况下,选择哪个对象作为锁定并不重要。但您必须始终使用相同的对象进行锁定才能实现正确的同步。上面的代码不能确保正确的同步,因为您曾经使用“this”对象作为锁,然后使用“lockObject”作为锁。

In this case it does not matter which object you choose for lock. But you must consistently use the same object for locking to achieve correct synchronization. Above code does not ensure proper synchronization as you once use the 'this' object as lock and next the 'lockObject' as lock.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文