java中加锁方式

答案

java中可以用 synchronized 关键字来保证多行代码的原子性,它的语法为:

synchronized(obj) {
   // 多行要原子操作的代码
}

其中obj 被称为临界资源Critical Resource,如果一个线程执行到synchronized(obj) 时,此线程会对 obj 对象上锁,将 synchronized 语句块内的代码保护起来;这时有其它线程执行到synchronized(obj) 时只能在锁外排队等待。

即受synchronized 保护的多行代码同一时刻只能被一个线程执行,synchronized 将并行操作变成了串行操作(也称为同步操作)。

追问

synchronized 加在成员方法上和静态方法上有何不同?

答案

1) 加在成员方法上锁住的是this对象,例如:

public class TestSynchonized {  
  public synchronized void m1() {
  }
  public synchronized void m2() {
  }
}

当创建了该类的两个对象o1和o2后,如果有两个线程t1和t2前来访问,则:

调用方式 结果 理由
t1 先调用o1.m1(), t2 紧接着调用o1.m1() t2阻塞 t1锁住了o1对象
t1 先调用o1.m1(), t2 紧接着调用o1.m2() t2阻塞 t1锁住了o1对象
t1 先调用o1.m1(), t2 紧接着调用o2.m1() t2不阻塞 它们分别锁住不同对象
t1 先调用o1.m1(), t2 紧接着调用o2.m2() t2不阻塞 它们分别锁住不同对象

2) 加在静态方法上锁住的是类对象,例如:

public class TestSynchonized {  
  public synchronized static void m1() {
  }
  public synchronized static void m2() {
  }
  public synchronized void m3() {
  }
}

当创建了该类的两个对象o1和o2后,如果有两个线程t1和t2前来访问,则:

调用方式 结果 理由
t1 先调用o1.m1(), t2 紧接着调用o1.m1() t2阻塞 t1锁住了TestSynchonized.class对象
t1 先调用o1.m1(), t2 紧接着调用o1.m2() t2阻塞 t1锁住了TestSynchonized.class对象
t1 先调用o1.m1(), t2 紧接着调用o2.m1() t2阻塞 t1锁住了TestSynchonized.class对象
t1 先调用o1.m1(), t2 紧接着调用o2.m2() t2阻塞 t1锁住了TestSynchonized.class对象
t1 先调用o1.m1(), t2 紧接着调用o1.m3() t2不阻塞 t1锁住了TestSynchonized.class对象,而t2锁住的是o1
t1 先调用o1.m1(), t2 紧接着调用o2.m3() t2不阻塞 t1锁住了TestSynchonized.class对象,而t2锁住的是o2

results matching ""

    No results matching ""