如果我在同一个类上同步两个方法,它们可以同时运行吗?

She*_*lef 143 java multithreading synchronized java-threads

如果我在同一个类上同步两个方法,它们可以同时在同一个对象上运行吗?例如:

class A {
    public synchronized void methodA() {
        //method A
    }

    public synchronized void methodB() {
        // method B
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道我不能methodA()在两个不同的线程中对同一个对象运行两次.同样的事情methodB().

但是,在运行methodB()时我可以在不同的线程上methodA()运行吗?(同一个对象)

NPE*_*NPE 134

两种方法都锁定同一台显示器.因此,您不能在不同线程的同一对象上同时执行它们(两个方法中的一个将阻塞,直到另一个完成).

  • 请记住,静态方法对`.class`对象使用锁定.所以如果你有'class A {static synchronized void m(){}}`.然后一个线程调用`new A().m()`它获取对`new A()`对象的锁定.如果那么另一个线程调用`Am()`它__ENTERS THE METHOD NO PROBLEM__因为它查找的是锁定`A.class`对象而__NO THREADS拥有这种锁___.所以,即使你声明方法`synchronized`,它实际上__IS被两个不同的线程__AT访问____相同的时间___.因此:__never使用对象引用来调用静态方法___ (7认同)
  • @ amod0017:当`methodB()`是`static`时,`obj.methodB()`与`A.methodB()`同义.因此,是的,他们将阻止(在类,而不是对象,监视器). (2认同)

Nat*_*hes 101

在示例中,methodA和methodB是实例方法(与静态方法相对).把synchronized上一个实例方法意味着该线程必须获取关于对象实例锁(以下简称"本征锁"),该方法被称为在线程之前可以开始在该方法中执行的任何代码.

如果您有两个标记为synchronized的不同实例方法,并且不同的线程在同一个对象上同时调用这些方法,那么这些线程将争用同一个锁.一旦一个线程获得锁定,所有其他线程就会被该对象上的所有同步实例方法关闭.

为了使两个方法同时运行,它们必须使用不同的锁,如下所示:

class A {
    private final Object lockA = new Object();
    private final Object lockB = new Object();

    public void methodA() {
        synchronized(lockA) {
            //method A
        }
    }

    public void methodB() {
        synchronized(lockB) {
            //method B
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

其中synchronized块语法允许指定执行线程需要获取内部锁定的特定对象才能进入块.

要理解的重要一点是,即使我们在单个方法上放置"同步"关键字,核心概念也就是幕后的内在锁定.

以下是Java教程描述关系的方式:

同步是围绕称为内部锁或监视器锁的内部实体构建的.(API规范通常将此实体简称为"监视器".)内部锁在同步的两个方面都发挥作用:强制对对象状态进行独占访问,并建立对可见性至关重要的先发生关系.

每个对象都有一个与之关联的内在锁.按照惯例,需要对对象字段进行独占和一致访问的线程必须在访问对象之前获取对象的内部锁,然后在完成它们时释放内部锁.据说一个线程在获得锁定和释放锁定之间拥有内在锁定.只要一个线程拥有一个内部锁,没有其他线程可以获得相同的锁.另一个线程在尝试获取锁时将阻塞.

锁定的目的是保护共享数据.只有在每个锁保护不同的数据成员时,才会使用上面示例代码中所示的单独锁.

  • @Nimrod:它锁定在 lockA 和 lockB 对象上,而不是锁定在 A 的实例上。这里没有锁定一个类。类级锁定意味着获取类对象的锁定,使用类似“静态同步”或“同步(A.class)”之类的东西 (2认同)

Sri*_*nth 15

Java Thread 在进入实例同步java方法时获取对象级锁,并在进入静态同步java方法时获取类级锁.

在您的情况下,方法(实例)属于同一类.因此,当线程进入java synchronized方法或块时,它获取一个锁(调用该方法的对象).因此,在完成第一个方法并释放lock(on object)之前,不能在同一个对象上同时调用其他方法.


Ole*_*_DJ 12

在您的情况下,您在同一个类实例上同步了两个方法.因此,这两个方法不能同时在同一个A类实例的不同线程上运行.但它们可以在不同的A类实例上运行.

class A {
    public synchronized void methodA() {
        //method A
    }
}
Run Code Online (Sandbox Code Playgroud)

是相同的:

class A {
    public void methodA() {
        synchronized(this){
            // code of method A
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Adi*_*a W 7

来自oracle文档链接

使方法同步有两个影响:

首先,对同一对象的两个同步方法的调用不可能进行交错.当一个线程正在为对象执行同步方法时,所有其他线程调用同一对象的同步方法(暂停执行)直到第一个线程完成对象.

其次,当同步方法退出时,它会自动与同一对象的同步方法的任何后续调用建立先发生关系.这可以保证对所有线程都可以看到对象状态的更改

这将回答您的问题:在同一个对象上,当第一个同步方法执行正在进行时,您无法调用第二个同步方法.

查看此文档页面以了解内部锁定和锁定行为.


Kho*_*ari 5

将您的代码视为以下代码:

class A {

public void methodA() {
    synchronized(this){        
      //method A body
    }
}

public void methodB() {
    synchronized(this){
      // method B body
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,在方法级别同步仅表示已同步(此)。如果有任何线程运行此类的方法,它将在开始执行之前获取该锁,并保持该锁直到该方法的执行完成。

但是,当methodA()仍在运行时,我可以在其他线程上运行methodB()吗?(相同的对象)

确实,这是不可能的!

因此,多个线程将无法在同一对象上同时运行任何数量的同步方法。

  • 因为它们是不同的对象,所以它们会。也就是说,如果要防止这种情况,可以使用静态方法并同步该类,或者将类变量对象用作锁,或者使类成为Singleton。@Yug Singh (2认同)