如果我在同一个类中有2个同步方法,但是每个方法访问不同的变量,2个线程可以同时访问这2个方法吗?锁是发生在对象上,还是与同步方法中的变量一样特定?

例子:

class X {

    private int a;
    private int b;

    public synchronized void addA(){
        a++;
    }

    public synchronized void addB(){
        b++;
    }

}

两个线程可以同时访问类X的同一个实例,执行x.a da()和x.a bbb()吗?


当前回答

Synchronized在方法声明上是语法糖:

 public void addA() {
     synchronized (this) {
          a++;
     }
  }

在静态方法中,它是这样的语法糖:

 ClassA {
     public static void addA() {
          synchronized(ClassA.class) {
              a++;
          }
 }

我认为,如果Java设计人员当时就知道现在对同步的理解,他们就不会添加语法糖,因为它通常会导致糟糕的并发实现。

其他回答

被访问的锁在对象上,而不是方法上。在方法中访问哪些变量无关紧要。

在方法中添加"synchronized"意味着运行代码的线程必须在继续之前获得对象上的锁。添加“static synchronized”意味着运行代码的线程必须在继续之前获取类对象上的锁。或者,你也可以像这样将代码封装在一个块中:

public void addA() {
    synchronized(this) {
        a++;
    }
}

这样您就可以指定必须获取其锁的对象。

如果你想避免锁定包含对象,你可以选择:

使用指定不同锁的同步块 使a和b具有原子性(使用java.util.concurrent.atomic)

Synchronized在方法声明上是语法糖:

 public void addA() {
     synchronized (this) {
          a++;
     }
  }

在静态方法中,它是这样的语法糖:

 ClassA {
     public static void addA() {
          synchronized(ClassA.class) {
              a++;
          }
 }

我认为,如果Java设计人员当时就知道现在对同步的理解,他们就不会添加语法糖,因为它通常会导致糟糕的并发实现。

在java同步中,如果一个线程想要进入同步方法,它将获得该对象的所有同步方法的锁,而不仅仅是线程正在使用的一个同步方法。 因此,执行addA()的线程将获得对addA()和addB()的锁,因为两者都是同步的。因此具有相同对象的其他线程不能执行addB()。

是的,它将阻塞其他方法,因为synchronized方法应用于指向....的WHOLE类对象但无论如何,它只会在addA或addB方法中执行求和时阻塞其他线程的执行,因为当它完成…一个线程将释放对象,另一个线程将访问另一个方法,以此类推。

我的意思是“同步”是为了在特定的代码执行中阻止另一个线程访问另一个线程而精确制作的。最后这段代码就可以正常工作了。

作为最后的注意,如果有一个'a'和'b'变量,而不仅仅是一个唯一的变量'a'或任何其他名称,没有必要同步这个方法,因为它是完全安全的访问其他var(其他内存位置)。

class X {

private int a;
private int b;

public void addA(){
    a++;
}

public void addB(){
    b++;
}}

也会起作用

如果你将方法声明为synchronized(就像你通过输入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();
    }
}