为了账号安全,请及时绑定邮箱和手机立即绑定

Java同步方法锁定对象,还是方法?

Java同步方法锁定对象,还是方法?

繁花不似锦 2019-10-14 11:01:29
如果我在同一个类中有2个同步方法,但是每个方法都访问不同的变量,那么2个线程可以同时访问这2个方法吗?锁是否发生在对象上,或者是否与同步方法中的变量一样具体?例:class X {    private int a;    private int b;    public synchronized void addA(){        a++;    }    public synchronized void addB(){        b++;    }}2个线程可以访问类X执行相同的实例x.addA(),并x.addB()在同一时间?
查看完整描述

3 回答

?
四季花海

TA贡献1811条经验 获得超5个赞

如果将方法声明为已同步(就像通过键入所做的那样public synchronized void addA()),则会在整个对象上进行同步,因此,从同一对象访问不同变量的两个线程将始终相互阻塞。


如果您一次只想同步一个变量,那么两个线程在访问不同变量时不会互相阻塞,您可以分别以synchronized ()块同步。如果a和b是对象引用,则可以使用:


public void addA() {

    synchronized( a ) {

        a++;

    }

}


public void addB() {

    synchronized( b ) {

        b++;

    }

}

但是由于它们是原始类型,所以您不能这样做。


我建议您改用AtomicInteger:


import java.util.concurrent.atomic.AtomicInteger;


class X {


    AtomicInteger a;

    AtomicInteger b;


    public void addA(){

        a.incrementAndGet();

    }


    public void addB(){ 

        b.incrementAndGet();

    }

}


查看完整回答
反对 回复 2019-10-14
?
largeQ

TA贡献2039条经验 获得超7个赞

为此,在方法声明上同步的是语法糖:


 public void addA() {

     synchronized (this) {

          a++;

     }

  }

在静态方法上,它是语法糖:


 ClassA {

     public static void addA() {

          synchronized(ClassA.class) {

              a++;

          }

 }

我认为,如果Java设计人员知道了现在对同步的了解,他们将不会添加语法糖,因为它经常会导致并发的不良实现。


查看完整回答
反对 回复 2019-10-14
?
九州编程

TA贡献1785条经验 获得超4个赞

从“ Java™教程”中的同步方法开始:


首先,不可能对同一对象的两次同步方法调用进行交织。当一个线程正在执行对象的同步方法时,所有其他调用同一对象块的同步方法的线程(挂起执行),直到第一个线程对该对象完成。


在同步块上的“ Java™教程”中:


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


(强调我的)


假设您有2个非交织变量。因此,您希望同时从不同的线程访问每个线程。您需要定义锁不上对象类本身,而是对类对象像下面(例如,从第二个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++;

        }

    }

}


查看完整回答
反对 回复 2019-10-14
  • 3 回答
  • 0 关注
  • 831 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信