同步语句 - 创建对象以提供锁定,因此c1的更新不会与c2的更新交错

时间:2016-02-17 05:20:44

标签: java multithreading

我是Java的新手,正在尝试学习同步语句的概念。我在Java Tutorial Oracle中看到了下面的段落和代码。我的问题是

1)在什么样的情况下,c1的更新与c2的更新交错。

2)对象'lock1'和'lock2'如何通过更新c2来阻止更新c1交错。

我真的很难理解这个概念。

  

同步语句对于提高并发性也很有用   细粒度的同步。例如,假设MsLunch类有   两个实例字段,c1和c2,从不一起使用。所有   必须同步这些字段的更新,但没有理由   防止c1的更新与c2的更新交错 -   这样做可以通过创建不必要的阻塞来减少并发性。   而不是使用同步方法或以其他方式使用锁   与此相关,我们创建两个对象仅用于提供锁定。

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++;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

如果您有同步方法:

private void lblBackupMouseEntered(java.awt.event.MouseEvent evt) {
 lblBackup.setSize(lblBackup.getWidth()+5,lblBackup.getHeight()+5);
}                                      

private void lblChangePasswordMouseEntered(java.awt.event.MouseEvent evt) {
 lblChangePassword.setSize(lblChangePassword.getWidth()+5,lblChangePassword.getHeight()+5);
}

private void lblAddEmployeeMouseEntered(java.awt.event.MouseEvent evt) {
 lblAddEmployee.setSize(lblAddEmployee.getWidth()+5,lblAddEmployee.getHeight()+5);
}

private void lblAddCustomerMouseEntered(java.awt.event.MouseEvent evt) {
 lblAddCustomer.setSize(lblAddCustomer.getWidth()+5,lblAddCustomer.getHeight()+5);
}  

隐式转换为:

public synchronized void inc1() {
        c1++;
}

所以,如果你同时制作public void inc1() { synchronized(this) { c1++; } } inc1 同步方法,那么他们都需要掌握当前对象(inc2)监视器和然后增量

但是由于thisc1++是独立的,所以不应该阻止它们,因为我们使用的是单个锁。我们必须确保的是,应以单独的沙盒方式阻止对c2++inc1()的多次调用,即线程1对inc2()的访问不应阻止对inc1()的访问通过thread-2。拥有不同的锁会做到这一点。

答案 1 :(得分:1)

暗示可能有其他线程使用相同的MsLunch对象。例如,您可以像这样开始两个线程:

MsLunch ml = new MsLunch();

Thread thread1 = new Thread() {
    public void run() { while (true) ml.inc1(); }
};

Thread thread2 = new Thread() {
    public void run() { while (true) ml.inc2(); }
};

thread1.start();
thread2.start();

现在有两个并行运行的线程,一个在循环中调用inc1(),另一个在循环中调用inc2()

通过为这两种方法分别使用锁,两个线程不会相互减慢速度。如果您有共享锁,则inc1()inc2()将无法同时运行。任何时候你打电话给对方都会阻止,直到第一次通话结束。

Thread thread3 = new Thread() {
    public void run() { while (true) ml.inc2(); }
};

将此与您添加第三个也调用inc2()的线程的情况进行对比。线程#1可以随意调用inc1()。同时,线程#2和#3都想要调用inc2(),所以他们会互相争斗。如果线程#2正在调用inc2(),则线程#3将阻塞,直到该调用结束。反之亦然,如果线程#3处于调用的中间,那么线程#2将不得不等待。