本节主要是关于Synchronized关键字的对象锁和升级后的类锁。
----------------------------------------------------------------对象锁------------------------------------------------------------------
先看下面一个例子:
public class MyObjec extends Thread {
private int num = 0;
public void method1() {
try {
num = num + 100;
System.out.println("I am method1!" + num);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void method2() {
num = num + 200;
Thread.sleep(0);
System.out.println("I am method2!" + num);
}
public static void main(String[] args) {
MyObject m = new MyObject();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
m.method1();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
m.method2();
}
});
t1.start();
t2.start();
}
}
在这个情况下,num产生的结果无非有两种
结果1:
I am method1!100
I am method2!300
结果2:
I am method2!300
I am method1!300
或者
I am method2!200
I am method1!300
为什么会出现这中情况,前面一节已经讲述。下面看看为method1添加synchronized后出现的情况:
结果1:
I am method1!300
I am method2!200
结果2:
I am method2!300
I am method1!100
结果3:
I am method2!300
I am method1!300
为啥加了没加一样的效果?前面说过,synchronized是对象锁,那么这里为什么没有将method2也进行锁起来,不让后面的m调用,这就涉及synchronized的异步问题。synchronized只是将本方法涉及的对象加锁,其锁定的范围还是该对象内的该方法,该对象内的其他没有添加Synchronized的方法是不受这个锁管辖的,可以理解成synchronized就是一个该对象锁能否管辖的标志位,有这个标志位,该方法就能被管辖,没有这个标志位,该方法就不能被锁管辖。
可以想象,如果method2也加上synchronized后,结果 肯定是:
I am method1!100
I am method2!300
----------------------------------------------------------------类锁------------------------------------------------------------------
下面对上面的例子进行改动,main方法改成:
public static void main(String[] args) {
MyObject m1 = new MyObject();
MyObject m2 = new MyObject();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
m1.method1();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
m2.method2();
}
});
t1.start();
t2.start();
}
}
上面程序执行的结果是三种情况:
结果1:
I am method1!300
I am method2!200
结果2:
I am method2!300
I am method1!100
结果3:
I am method2!300
I am method1!300
如果想要按照顺序执行,原本的单单加上Synchronized肯定是不行的(原因见前节),那么就需要加上static关键字进行将对象锁升级为类锁:
这样就会变成想要达到的效果。