如果我同步在同一类的两种方法,它们可以同时运行?(If i synchronized two met

2019-07-21 17:43发布

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

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

    public synchronized void methodB() {
        // method B
    }
}

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

但是我可以运行methodB()在不同的线程同时methodA()仍在运行? (相同的对象)

Answer 1:

这两种方法都锁定同一监视器。 因此,不能同时从不同的线程相同的对象(两种方法之一将阻塞,直到另一个是成品)上执行它们。



Answer 2:

在该示例中和了methodA是的methodB实例方法(相对于静态方法)。 把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
        }
    }
}

其中同步块语法允许指定正在执行的线程需要对取得的固有锁,以便进入所述块中的特定对象。

要了解的重要一点是,即使我们正在对个别方法“同步”的关键词,核心理念是幕后的内部锁。

下面是如何在Java教程介绍的关系:

同步是围绕被称为内在锁或监视器锁定内部实体建造。 (API规范通常是指这个实体简称为“显示器”。)内在锁在同步的两个方面发挥作用:执行一个对象的状态和建立之前发生是能见度的关系至关重要独占访问。

每个对象都有一个与之关联的内部锁。 按照惯例,需要一个对象的字段独家一致的访问一个线程访问之前,获取物体的内部锁,然后当它与他们所做的释放内部锁。 一个线程被说成自己的,它已经收购了锁和释放锁的时间之间的内在锁。 只要一个线程拥有一个内部锁,没有其他线程可以获取同样的锁。 当它试图获取锁,其他的线程将阻塞。

锁定的目的是为了保护共享数据。 你可以使用单独的锁所示的示例代码仅以上如果每个锁保护的不同数据成员。



Answer 3:

当它进入一个实例同步Java方法,并且当它进入静态同步的java方法获取类级锁 Java线程获取对象级锁

在你的情况下,方法(实例)是同一类的。 因此,当过线程进入到Java同步方法或阻止它获取一个锁(在其上调用方法的对象)。 因此其他方法不能在同一时间在同一对象上,直到第一种方法完成,并且锁(上对象)被释放调用。



Answer 4:

在你的情况,你对类的同一个实例同步的两个方法。 因此,这两种方法不能同时在不同的线程类A的同一个实例的运行,但是它们可以在不同的A类实例。

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

是相同的:

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


Answer 5:

从Oracle文档链接

同步制作方法有两个作用:

首先,它是不可能的同一对象上同步方法来交错两个调用。 当一个线程正在执行的对象同步方法,来调用同步方法针对同一对象块(挂起执行),直到第一线程所有其他线程与该对象进行。

其次,当一个同步方法退出时,它自动地建立与用于相同对象的同步方法的任何后续调用一个之前发生的关系。 这保证了更改对象的状态是可见的所有线程

这将会回答你的问题:在同一个对象,你不能叫第二同步方法时,第一个synchronized方法执行过程中。

看看这个文档页面 ,了解内在的锁和锁的行为。



Answer 6:

想想你的代码作为一个如下的:

class A {

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

public void methodB() {
    synchronized(this){
      // method B body
    }
}

因此,在方法级同步仅仅意味着同步(本)。 如果任何线程中运行这个类的一个方法,它会在开始执行之前获得锁,并保持,直到方法执行完毕。

但我可以在不同的线程上运行的methodB(),而了methodA()仍在运行? (相同的对象)

事实上,这是不可能的!

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



Answer 7:

公正对待所有的清晰度,这有可能是因为一个是有对象级锁和其他类级锁静态同步和非静态同步方法可同时或同时运行。



Answer 8:

你是在对象同步它不是类。 所以,他们不能在同一对象上同时运行



Answer 9:

否它是不可能的,如果有可能则两个方法可以同时更新相同的变量,其可以很容易地破坏数据。



Answer 10:

与不容易下沉同步的核心思想是,它才会有效果只有在呼吁同一个对象实例的方法-它已经在答案和评论强调-

下面的示例程序是清楚地找出相同的 -

public class Test {

public synchronized void methodA(String currentObjectName) throws InterruptedException {
    System.out.println(Thread.currentThread().getName() + "->" +currentObjectName + "->methodA in");
    Thread.sleep(1000);
    System.out.println(Thread.currentThread().getName() + "->" +currentObjectName + "->methodA out");
}

public synchronized void methodB(String currentObjectName)  throws InterruptedException {
    System.out.println(Thread.currentThread().getName() + "->" +currentObjectName + "->methodB in");
    Thread.sleep(1000);
    System.out.println(Thread.currentThread().getName() + "->" +currentObjectName + "->methodB out");
}

public static void main(String[] args){
    Test object1 = new Test();
    Test object2 = new Test();
    //passing object instances to the runnable to make calls later
    TestRunner runner = new TestRunner(object1,object2);
    // you need to start atleast two threads to properly see the behaviour
    Thread thread1 = new Thread(runner);
    thread1.start();
    Thread thread2 = new Thread(runner);
    thread2.start();
}
}

class TestRunner implements Runnable {
Test object1;
Test object2;

public TestRunner(Test h1,Test h2) {
    this.object1 = h1;
    this.object2 = h2;
}

@Override
public void run() {
    synchronizedEffectiveAsMethodsCalledOnSameObject(object1);
    //noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects(object1,object2);
}

// this method calls the method A and B with same object instance object1 hence simultaneous NOT possible
private void synchronizedEffectiveAsMethodsCalledOnSameObject(Test object1) {
    try {
        object1.methodA("object1");
        object1.methodB("object1");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

// this method calls the method A and B with different object instances object1 and object2 hence simultaneous IS possible
private void noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects(Test object1,Test object2) {
    try {
        object1.methodA("object1");
        object2.methodB("object2");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
}

注意在如何同时访问允许预期 ,如果方法调用上,不同对象实例输出的差异。

输出中与noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects() 评论 -the输出是为了在了methodA>出了methodA ..的methodB在>的methodB缺货

和输出继电器与synchronizedEffectiveAsMethodsCalledOnSameObject() 评论 -输出表示由线程1和Thread0中突出显示的部分的了methodA同时访问-

增加线程的数量将使它更加明显。



Answer 11:

单个对象上执行一个共同的同步方法,两个不同的线程,因为对象是一样的,当一个线程与同步的方法使用它,它必须varify锁,如果启用了锁,这个线程会去等待状态,如果锁被禁用,那么它可以访问对象,而将访问它将使锁,将释放,只有当它的执行锁完成。 另一个线程到达时,它会varify锁,因为它被启用,将等到第一个线程完成他的执行力和释放锁把的对象,一旦锁被释放的第二个线程将获得访问对象和直到它的执行它将使锁。 这样的执行不会不并发的,两个线程将由一个中,当两个线程使用上的不同对象的同步方法,它们将同时运行执行一个。



文章来源: If i synchronized two methods on the same class, can they run simultaneously?