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 |