线程:同步块

时间:2013-02-11 10:11:58

标签: java multithreading

我对同步块有疑问。执行以下代码后,我将输出为:

Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 1
Inside run=>thread 2
Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 1
Inside run=>thread 2

我期待输出,因为只有一个线程将首先执行synchronized块,然后只有第二个线程才能访问同步块。 我可能理解这个概念错了吗?

 package com.blt;

    public class ThreadExample implements Runnable {
        public static void main(String args[])
        {


            System.out.println("A");
            Thread T=new Thread(new ThreadExample());
            Thread T1=new Thread(new ThreadExample());
            System.out.println("B");
            T.setName("thread 1");
            T1.setName("thread 2");
            System.out.println("C");
            T.start();
            System.out.println("D");
            T1.start();
        }


     synchronized public void run()
    {
        for(int i=0; i<5; i++)
        {
            try
            {
             System.out.println("Inside run=>"+Thread.currentThread().getName());
             Thread.currentThread().sleep(2000);
            }
             catch(InterruptedException e)
            {
                e.printStackTrace();
            }
          }  
    }
    }

5 个答案:

答案 0 :(得分:4)

每个线程都在不同的对象上进行同步。所以,是的,他们不会互相锁定。但更重要的是,run方法是为Runnable接口 定义的,没有 同步修饰符,您不应该向其添加一个({1}}方法正如你已经看到的那样,它没有你想象的效果。

要记住的关键是当你在方法上使用synchronized修饰符时:

public synchronized void someMethod();

与使用synchronized(this)实际上是一回事。在这两种情况下,您都锁定了对象监视器。如果您有多个对象,则可以有多个监视器。

以下是您自己的示例的修改版本,它将按预期更有效。它使用公共对象监视器(在本例中为您的类本身),以便同步按预期工作:

public class ThreadExample implements Runnable {
    public static void main(String args[]) {
        System.out.println("A");
        Thread T = new Thread(new ThreadExample());
        Thread T1 = new Thread(new ThreadExample());
        System.out.println("B");
        T.setName("thread 1");
        T1.setName("thread 2");
        System.out.println("C");
        T.start();
        System.out.println("D");
        T1.start();
    }

    public void run() {
        synchronized (ThreadExample.class) {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println("Inside run=>"
                            + Thread.currentThread().getName());
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

答案 1 :(得分:3)

您的问题是,如果2个同步的块没有在同一台显示器上锁定,则它们不是互斥的。

请记住,this监视器上的同步方法会锁定 - 您的代码等同于:

 public void run() {
    synchronized(this) {
        //your code here
    }
 }

由于您创建了两个ThreadExample个实例,因此每个实例都有一个不同的this

您可以在两个线程中使用相同的锁来解决您的问题,例如:

 public void run() {
    synchronized(ThreadExample.class) {
        //your code here
    }
 }

甚至更好,只根据Quoi指出的ThreadExample创建一个实例。

答案 2 :(得分:1)

您创建了两个ThreadExample对象,因此每个线程都有不同的synchronized方法。

创建一个Object并将引用传递给线程,您将看到同步效果。:)

ThreadExample thex = new ThreadExample();
Thread T=new Thread(thex);
Thread T1=new Thread(thex);

这里两个线程都使用相同的synchronized方法。

答案 3 :(得分:0)

呃,你正在同步每个线程的 run 方法。 Thread1不会尝试运行Thread2的run方法,反之亦然。这就是为什么它实际上与完全不同步一样。

答案 4 :(得分:0)

您正在创建该类的两个实例,并且您正在同步类,因此它们将独立运行,因为没有公共锁。他们将继续单独运行。