在同一类中使用同步块来处理不同的方法

17 浏览
0 Comments

在同一类中使用同步块来处理不同的方法

我正在阅读来自oracle的多线程官方教程,我遇到了这个例子(假设从未同时使用):

public class MsLunch {
    private long c1 = 0;
    private long c2 = 0;
    private Object lock1 = new Object();
    private Object lock2 = new Object();
    public void inc1() {
        synchronized(lock1) {
            c1++;
        }
    }
    public void inc2() {
        synchronized(lock2) {
            c2++;
        }
    }
}

据说使用lock1和lock2有助于减少不必要的阻塞,相比于在synchronized块中使用this关键字。

然而,我并没有看到这如何帮助减少阻塞,因为它们彼此之间没有依赖关系。我有多个线程同时运行这两个方法,当我使用锁对象和this关键字时性能相当相似。

有人能帮忙解释一下我的困惑吗?希望能用一个例子来清楚地说明区别。


在这里补充一下,这个帖子也帮助我澄清了疑惑。关键点:在方法上使用synchronized意味着线程必须在进入该方法之前获取对象实例的锁。

0
0 Comments

使用同步块来保护同一个类中的不同方法的原因是为了防止线程之间的干扰。如果使用不同的锁来保护inc1和inc2,那么线程X可以在另一个线程正在运行inc2时运行inc1。如果它们使用相同的锁(无论是this还是其他锁对象),则无法同时运行它们两个。因此,至少在理论上,使用两个不同的锁应该提高这种情况下的性能。

我理解你的观点。我想我困惑的是,如果在这种情况下,c1和c2分别由两个方法更新,那么使用两个不同的锁是否会影响性能,与只使用一个锁相比。根据你的回答,我认为你的意思是使用相同的锁的同步块不会同时运行 - 在这种情况下,如果在不同的线程上正在更新c1,那么c2将不会被更新?

确切地说,这就是我们使用锁的原因 - 无论它们是否在运行相同的方法,都可以阻止一个线程干扰另一个线程。

关键是,由于您正在尝试保护两个独立的变量,您可以使用两个独立的锁。如果线程A正在调用inc1(),那不应该阻止线程B进入inc2()。

谢谢,当一个线程访问其中一个块时,使用相同锁的同步块将全部被锁定。这样理解对吗?

没错,完全正确。

0