java - 方法同步与对象同步有什么区别?

标签 java multithreading thread-safety thread-synchronization

这个问题在这里已经有了答案:




9年前关闭。




Possible Duplicate:
synchronized block vs synchronized method?



如果有人可以帮助我提供有关方法同步与对象同步之间有什么不同的真实示例,那就太好了。

方法同步示例
public class MyClassExample {
private int i;
public synchronized void increment(){
    i = i + 1;
}
}

对象同步示例
public class MyClassExample {
private int i;
Object writeLock = new Object();
 public void increment(){
    synchronized(writeLock) {
        i = i + 1;
    }
}
}

最佳答案

tl; dr - 外部同步使您容易受到攻击(有意或无意),并且还迫使您进行可能不需要的锁定检查。在这个答案的最底部也有 Nerd 的好信息。

同步方法几乎与同步方法相同(见底部):

synchroinzed void foo() {

}

void foo() {
    synchronized(this) {

    }
}

通过使方法本身不是 synchronized ,您允许自己锁定任何 Object ,不仅仅是 this .我个人建议在内部同步 Object ,像这样
private final Object foolock = new Object();

void foo() {
    synchronzied(foolock) {

    }
}

原因是,如果你做 synchronized方法,有效锁定 this其他人可以 synchronize在你身上并将你锁在你的 Object 之外!想象一下:
class FooDoer {
    // removed! using synchronized methods instead
    //final Object foolock = new Object();

    synchronized void foo() {

    }
}

// thread 1 - attacker
FooDoer f = new FooDoer();
globalMap.put("TheFoo",f);
synchronized(f) {
    while(true); // haha!
}

// thread 2 - victim
FooDoer f = globalMap.get("TheFoo");
f.foo(); // locked, because Thread 1 has locked us out!

它使您面临拒绝服务攻击。这不好!通过将锁设为内部,作为类的作者,您可以准确控制谁可以锁定对象的哪些区域以及在哪些条件下。

另一个问题是您可能没有用于检查的 protected 数据。例如:
synchronized void foo() {
    if(expensiveAccessCheck()) {
        update();
    }
}

void foo() {
    if(expensiveAccessCheck()) {
        synchronized(foolock) {
            update();
        }
    }
}

在这种情况下,当您坐在那里转动车轮时,您不必让其他人等待。也许您正在从 URL 中抓取数据然后进行更新。为什么要让其他人保持锁定在数据之外?在这种情况下,较低的粒度更好。

现在你可能还记得我之前说的几乎相同。两者之间存在微小,微小,微小的差异。同步方法会将同步指令烘焙到字节码中的方法签名中。这将使字节码缩短 1 个字节,因为它不需要进行额外的调用。这可能会产生很小的影响,因为方法字节码中的字节数是决定是否内联的因素之一。尽管有这些细节,我强烈建议将它们视为相同的,因为这是一种微观优化,在生产环境中几乎不会发挥重要作用。当它们不是相同时,将其称为相同是不完整的。

关于java - 方法同步与对象同步有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12397427/

相关文章:

java - 为什么有关线程的代码显示a = 1和b = 3?为什么添加 "volatile"不起作用?

javascript - 如果我不离开单元格/字段,Primefaces 将无法识别单元格/字段的值。

java - 我如何将 JTextArea 添加到此代码中?

java - JDBC 告诉无法找到列

c - 在内核线程启动时使用 use_mm 和 set_fs

java - 这个函数是原子函数吗?

java - 需要字符串匹配器正则表达式

java - Notify 和 NotifyAll 仅影响处于阻塞状态的线程

c++ - std::thread::join 何时会因 no_such_process 而失败

c++ - iostream线程安全,cout和cerr一定要分开加锁吗?