对象上的线程锁是否也确保锁定成员对象?

时间:2012-05-21 07:06:14

标签: java multithreading thread-safety

考虑下面我编写的用于测试非原始变量(myObject)的锁定的类。如果所有线程都在SynchronizationTest的同一对象实例上工作,那么我的问题是:

我理解如果thread1正在执行set(...)方法,那么任何其他线程(比如说thread2)都可以执行anotherSetWithSynchronized(...)anotherSetWithoutSynchronized(...)

  1. 如果thread1在执行SynchronizationTest时锁定了set(...)的对象,是否意味着它已获取所有成员对象变量的锁定?就像在这种情况下myObject。如果没有,

  2. 如果thread1正在执行set(...),那么thread2可以同时执行anotherSetWithSynchronized(...)吗?

  3. 两个方法都不能同时由线程执行吗?

  4. 这个设计错了吗?我是否需要在myObject synchronized方法中明确锁定set(...)。像这样:

    public synchronized void set(MyValue myValue) {
        synchronized (myObject) {
            myObject.put(myValue);
        }
    } 
    
  5. 这是我的代码:

    public class SynchronizationTest {
      private MyObject myObject = new MyObject();
    
      public synchronized void set(MyValue myValue) {
        myObject.put(myValue);
      }
    
      public void anotherSetWithSynchronized(MyValue myValue) {
        synchronized (myObject) {
          myObject.put(myValue);
        }
      }
    
      public void anotherSetWithoutSynchronized(MyValue myValue) {
        myObject.put(myValue);
      }
    }
    

3 个答案:

答案 0 :(得分:6)

1:不,set(...)方法受“SynchronizationTest”对象锁定的保护。

2:是的,他们的防护对象与你设计的不同。

3:一个线程每次只能运行一个方法。如果你的意思是两个线程,正如我已经解释过的那样,这些方法由两个对象保护,因此它们可以同时执行

4:是的,你是对的。


Java中的内部锁定在“Java Concurrency In Practice”一书中描述如下:

  

同步块有两部分:对对象的引用   将作为锁,并由一个守卫的代码块   锁。同步方法是同步块的简写   跨越整个方法体,其锁是对象   该方法正在被调用。 (静态同步方法使用   锁的Class对象。)


有关更多详细信息,请参阅“实践中的Java并发”一节的第2.3.1节。

答案 1 :(得分:0)

  

对象上的线程锁定是否也确保锁定成员对象?

没有

  

据我所知,如果thread1正在执行set(...)方法,那么任何其他线程(比如说thread2)都可以执行另一个setWithSynchronized

是的,除非myObject与'this'具有相同的值。

答案 2 :(得分:0)

synchronized方法相当于

public void method(){
   synchronized(this){
      //something
   } 
}

1)没有

同步仅适用于指定的对象,而不适用于其成员。

2)没有

3)是的,他们不能,只有一个线程可以在由给定监视器保护的同步部分内激活

4)您不需要(如果使用显式同步,则不应在方法级别上使用synchronized)。但它更好(对于库/大型代码库),因为那时你可以控制谁可以访问发生同步的实例,所以其他人不能同步它并导致死锁。