包含其他对象的对象的synchronized方法

时间:2014-06-29 11:22:19

标签: java multithreading synchronized

如果我写一个"扩展Thread"并且对于该类的每个对象实例,都有另一个类的对象变量。例如:

public class MyClass extends Thread{

  private int num;
  private MyClass2 obj;
  public MyClass(int num, MyClass2 obj){
    this.num = num;
    this.obj = obj;
  }

在该类中我编写使用MyClass2方法的synchronized方法。例如:

  public synchronized int doSomething(){
    obj.someMethod();
  }

我的问题是:

1)当我从同步方法调用类MyClass2中的方法时,它仍然会被同步和原子化,或者当它为其他未同步的方法出去时它会继续与其他线程一起使用吗?

2)如果它将停止同步......我希望它同步,我是否需要制作" someMethod"在课堂上#34; MyClass2"还要同步?

3)如果我宣布两个不同的类对象" MyClass"但他们两个都有相同的" MyClass2"对象,如果调用doSomething方法,它们将被同步吗?

2 个答案:

答案 0 :(得分:2)

您可以将synchronized方法视为:

public int doSomething(){
    synchronized(this) //this is the protected object
    {
      obj.someMethod();
      //Whatever other code you my have within doSomething
    }
}

如果两个同步区域引用受保护对象,则不能同时运行,但这并不能避免未同步的代码使用此对象。

回答你的问题:

  • (问题1和2)在同步方法运行时,不会在受保护对象(在您的情况下为this)中没有同步区域的非同步方法或方法被阻止。
  • (问题3)没有他们不会,在这种情况下你需要保护obj,因为同步方法的隐式受保护对象是this,即方法正在进行的实例调用。

如果在obj个实例中使用MyClass引用,则必须同步对该对象的任何访问权限:

public int doSomething() {
    synchronized(obj) //Now, obj is the protected object
    {
      obj.someMethod();
    }
}

答案 1 :(得分:0)

在下面找到我的评论。

1)当我从同步方法调用类MyClass2中的方法时,它仍将是同步和原子的,或者当它出去用于其他未同步的方法时,它将继续与其他线程一起使用?   否。 MyClass2中的方法未同步。您需要明确地执行此操作

2)如果它将停止同步......我希望它同步,我是否需要制作" someMethod"在课堂上#34; MyClass2"还要同步?

是。 "的someMethod"应该同步

3)如果我宣布两个不同的类对象" MyClass"但他们两个都有相同的" MyClass2"对象,如果调用doSomething方法,它们将被同步吗?

每个线程都会获得新的MyClass2对象,因此不会在线程之间共享相同的数据。无需同步。虽然" someMethod"同步它是没有意义的,因为每个对象都拥有它自己的锁

运行以下代码并检查自己做的变化。

class MyClass extends Thread{

    private int num;
    private MyClass2 obj;
    public MyClass(int num, MyClass2 obj){
        this.num = num;
        this.obj = obj;
    }

    public synchronized void doSomething(){
        obj.someMethod(this.num);
    }

    public void run(){
        doSomething();
    }
}

class MyClass2{
    public synchronized void someMethod(int i){
        System.out.println(i+"--"+Thread.currentThread().getName());
        for(int j=0;j<10;j++){
            System.out.print(j);    
        }
        System.out.println();
    }
}

public class Main{
    public static void main(String[] arg){
        MyClass2 m=new MyClass2();
        for(int i=0;i<20;i++){
            new MyClass(i,m).start();
        }
    }
}