同步使对象锁定

时间:2010-06-23 18:23:04

标签: java multithreading

我对对象锁定感到困惑。 下面的类有4个方法,方法addB()是同步的。

在我的scienario中,有4个主题。当一个线程2访问addB()方法(它在Test对象上创建一个锁)时,是否会有其他任何线程同时访问addC()或addD()?

对象锁一次只允许一个线程吗?

class Test{
       private Integer a;
       private Integer b;
       private Integer c;
       private Integer d;


   public void addA(){
      synchronized(a) {
         a++;
      }
   }
   public synchronized void addB(){
         b++;
      }

   public void addC(){
         c++;
      }

   public void addD(){
         d++;
      }    
   }

编辑: 我有3个线程(t1,t2和t3),每个线程将访问addB(),addC()和addD()。如果线程t1访问方法addB(),可以同时线程t2访问addC()方法吗?如果不是t2状态会是什么?

class Test{
       private Integer a;
       private Integer b;
       private Integer c;
       private Integer d;


   public void addA(){
      synchronized(a) {
         a++;
      }
   }
   public synchronized void addB(){
         b++;
      }

   public synchronized void addC(){
         c++;
      }

   public synchronized void addD(){
         d++;
      }    
   }

5 个答案:

答案 0 :(得分:4)

锁确实一次只允许一个线程,但不同的锁不会相互影响。

在您的示例中,您有两个锁 - 一个位于属于a的互斥锁上,另一个位于属于this的互斥锁上(当您使用synchronized关键字时,这是隐式的,正如你在帖子中正确提到的那样)。

因此对addB()的调用将被同步,但不会阻止对任何其他方法的调用。如果一个线程持有this上的锁,则另一个线程可以保持a上的锁,并且多个其他线程可以同时执行addC()addD()

修改:除此之外,如果您真的使用AtomicInteger,您可能有兴趣了解Integer课程。它们提供原子操作,因此您无需担心它们之间的同步。

答案 1 :(得分:1)

您的代码中有两个锁,只有一个Thread可以遍历Lock#1或Lock#2。两个锁都是独立的,这意味着它们不会相互排除线程。

锁定#1在对象上同步

   public void addA(){
      synchronized(a) {
         a++;
      }
   }

lock#2在测试实例上同步(this)

   public synchronized void addB(){
         b++;
      }

addC()和addD()根本没有锁,任何数量的线程都可以同时访问它们。

答案 2 :(得分:1)

同步块只是一个环境,您可以将其作为reentrant lock“执行”的对象视为对象。实际上,只允许一个线程同时锁定一个对象。

方法C和D永远不会锁定,并且可以随时由任何线程执行。

正如其他人所指出的,当你执行a++时,你会创建一个新的Integer实例。

答案 3 :(得分:0)

Lock提供了一种同步线程的机制。这意味着在同一时间点只有一个线程可以访问对象的AddB方法。  除非在代码完成后释放锁,否则下一次代码迭代无法进入该块。

答案 4 :(得分:0)

锁定线程取决于所用对象的实例 e.g:

class MyClass extends Thread{
   Test instanceObj=null;    
   public MyClass(Test obj){
      instanceObj=obj;
   }

   public void run(){
      obj.addB();
   }
}

addB()函数可以重写为

public void addB(){
  synchronized(this){
    //func
 }
}
  • 此处锁定在对象上以访问该功能的片段。 其他功能可以被其他线程访问。
  • 更多关于addA的锁是在对象obj.a上有一个独立的锁。有两个不同的线程可以同时处理addA和addB。