在Java中执行两个同步块

时间:2012-08-10 11:45:26

标签: java multithreading

为什么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 个答案:

答案 0 :(得分:11)

你的陈述是错误的。只要不争用相同的锁,任意数量的同步块都可以并行执行。

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

最后,您可能会问“为什么我们需要相互排除代码段并行执行”。答案就是有许多数据结构只有在以某种方式组织时才有意义,当线程更新结构时,它必须逐个部分地进行,因此结构处于“损坏”状态而它正在进行更新。如果另一个线程在那一点出现并试图读取结构,或者更糟糕的是,自己更新它,整个事情就会崩溃。

修改

我看到了你的例子和你的评论,现在很明显是什么让你烦恼:方法的synchronized修饰语的语义。这意味着该方法将争夺this监视器上的锁定。同一个对象的所有synchronized方法都将争用同一个锁。

答案 1 :(得分:3)

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

示例

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
 }
}
}

如果Object的一个线程进入任何同步块,则同一个对象的所有其他线程 将必须等待该线程从synchronized块中退出以输入任何同步块块。如果有N个这样的块,则Object中只有一个线程一次只能访问一个块。请注意我强调相同对象的线程。如果我们处理来自不同对象的线程,则该概念将不适用。

我还要补充一点,如果您对进行锁定,上述概念将扩展到该类的任何对象。因此,如果不是说synchronized(this),而是使用synchronized(A.class),代码将指示JVM,无论该线程属于哪个Object,都要等待其他线程完成同步块执行。< / p>

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

答案 2 :(得分:0)

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

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

synchronized(object1){
    ...
}

synchronized(object2){
    ...
}

修改 Please reason the output for http://pastebin.com/tcJT009i

在您调用同步方法的示例中,锁定是通过同一对象获取的。尝试创建两个对象,然后查看。

答案 3 :(得分:0)

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

   synchronized(obj1){
       //your code here
   }

   synchronized(obj2){
       //your code here
   }

在上面的情况下,一个线程可以先执行,第二个可以执行第二个块,重点是这里线程正在使用不同的锁。

如果线程正在处理相同的lock,那么你的语句是正确的。如果一个线程获得了锁并执行了,那么每个对象只与java中的一个锁关联,那么其他线程必须等到第一个线程释放{ {1}}。可以通过lock块或方法获取锁定。