在Java中执行两个同步块

问题描述:

为什么两个同步块不能由Java中的两个不同线程同时执行。在Java中执行两个同步块

编辑

public class JavaApplication4 { 

    public static void main(String[] args) { 
     new JavaApplication4(); 
    } 

    public JavaApplication4() { 
     Thread t1 = new Thread() { 

      @Override 
      public void run() { 
       if (Thread.currentThread().getName().equals("Thread-1")) { 
        test(Thread.currentThread().getName()); 
       } else { 
        test1(Thread.currentThread().getName()); 
       } 
      } 
     }; 
     Thread t2 = new Thread(t1); 
     t2.start(); 
     t1.start(); 

    } 

    public synchronized void test(String msg) { 
     for (int i = 0; i < 10; i++) { 
      try { 
       Thread.sleep(100); 
      } catch (InterruptedException ex) { 
      } 
      System.out.println(msg); 
     } 
    } 

    public synchronized void test1(String msg) { 
     for (int i = 0; i < 10; i++) { 
      try { 
       Thread.sleep(100); 
      } catch (InterruptedException ex) { 
      } 
      System.out.println(msg + " from test1"); 
     } 
    } 
} 
+4

如果它们在不同的对象上同步,它们可以。如果它们在同一个对象上同步,那么同时执行就会失败目的。 – Keppil 2012-08-10 11:46:56

+0

我怀疑你有更深的担忧。你能改说你的问题吗? – 2012-08-10 11:50:40

+0

@Keppil请检查EDIT部分 – 2012-08-10 11:51:18

这就是整个同步的概念,如果你对对象(或类)进行锁定,其他线程都不能访问任何同步块。

Class A{ 

public void method1() 
{ 
synchronized(this)//Block 1 taking lock on Object 
{ 
    //do something 
} 
} 

public void method2() 
{ 
synchronized(this)//Block 2 taking lock on Object 
{ 
    //do something 
} 
} 
} 

如果对象的一个​​线程进入任何同步块,所有其他线程相同的对象的将必须等待线程出来的同步块的输入任何同步块。如果有N个这样的块,则对象中只有一个线程一次只能访问一个块。请注意我的重点是同一个对象的线程。如果我们正在处理来自不同对象的线程,这个概念将不适用。

我还要补充一点,如果你对采取锁定,上述概念将扩展到该类的任何对象。因此,如果不是说synchronized(this),我会使用synchronized(A.class),代码将指示JVM,即与线程所属的对象无关,使其等待其他线程完成同步的块执行。

编辑:请理解,当你正在进行锁定(通过使用同步关键字),你不只是锁定一个块。你正在锁定对象。这意味着你是在告诉JVM:“嘿,这个线程做一些关键工作这可能会改变对象(或类)的状态,所以不要让任何其他线程做任何其他重要工作”。关键工作,这里指的是同步块中的所有代码,它们锁定该特定对象(或类),而不仅仅在一个同步块中。

+0

但同步块是完全独立的。为什么它会被阻止。 – 2012-08-10 11:56:19

+0

你需要了解这个 - 你不是在块上采取锁,你是在对象(或类)采取锁 – Kamal 2012-08-10 11:57:34

你的说法是错误的。只要它们不争用相同的锁,任何数量的同步块都可以并行执行。

但是如果你的问题是关于争夺相同锁的块,那么问“为什么如此”是错误的,因为这是整个概念的目的。程序员需要互斥机制,他们从Java通过​​得到它。

最后,您可能会问“为什么我们需要将代码段并行排除在外”。答案是,有许多数据结构只有在以某种方式组织时才有意义,并且当线程更新结构时,它必然会一部分完成,因此结构处于“断开”状态而它正在更新。如果另一个线程在这一点上出现并尝试读取结构,或者更糟糕的是,自行更新它,整个事情就会崩溃。

编辑

我看到你的榜样,您的意见,现在很明显是什么困扰着你:​​修改的方法的语义。这意味着该方法将对this的显示器进行锁定。同一对象的所有​​方法将争用相同的锁。

+0

可以推理http://pastebin.com/tcJT009i – 2012-08-10 11:50:30

+0

的输出这段代码是一个相当可怕的恶梦。它检查,它没有明确设置和,差远了线程的名字,使用一个线程实例作为另一个线程的'Runnable'。我不敢预测会有什么样的后果。无论如何,我跑了它,它做了最明显的事情:两种方法相互排斥。 – 2012-08-10 11:53:43

+0

那只是一个虚拟的可怕代码。但我的问题是,为什么为t互斥的,当我没有发现任何错误在里面。两个不同的线程正在访问两个不同的同步块 – 2012-08-10 11:58:37

两个线程可以同时执行同步块,直到它们没有锁定同一个对象为止。

如果块在不同的对象上同步,它们可以同时执行。

synchronized(object1){ 
    ... 
} 

synchronized(object2){ 
    ... 
} 

编辑: Please reason the output for http://pastebin.com/tcJT009i

在当你调用锁定在同一个对象获得的同步方法的例子。尝试创建两个对象并查看。

这不是绝对正确的。如果你正在处理不同对象上的锁,那么多个线程可以执行这些块。

synchronized(obj1){ 
     //your code here 
    } 

    synchronized(obj2){ 
     //your code here 
    } 

在上述情况下,一个线程可以执行第一和第二可以执行第二块,所述点是这里线程与不同的锁工作。

你的说法是正确的,如果线程处理相同lock。每对象只有一个用Java锁有关,如果一个线程获取锁定并执行然后其他线程必须等待,直到第一个线程释放该lock .Lock能通过​​块或方法获得。