一个对象一把锁,不管锁这个对象的哪个引用,均是同一把锁。
基本原则是:
1.在synchronized块中不要改变该锁定对象在堆中内存的位置(貌似是根据对象的地址进行锁定)
2.synchronized不能锁null。
例子1:
public class SynTest {
public static String obj;
public static void main(String[] args) {
obj = new String("ab");
Thread t = new Thread(new SynThread(4));
t.start();
Thread t1 = new Thread(new SynThread(5));
t1.start();
}
public static String getObj() {
return obj;
}
public static void setObj(String obj) {
SynTest.obj = obj;
}
}
public class SynThread extends SynTest implements Runnable{
private int k;
public SynThread(int k){
this.k = k;
}
@Override
public void run() {
String str = null;
while(true) {
synchronized (str = getObj()){
try {
setObj(new String("change"));//这里改变原锁定对象到新对象、新的堆内存地址,
System.out.print(obj + k); //另一个线程synchronized则会立即得到新对象的锁,
Thread.sleep(2000); //当前线程还是锁着旧对象。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
例子2:
public class test {
public static Long num = 0L;
public static void main(String[] args){
for (int i = 0; i < 10; ++i){
Thread thread = new Thread(new test().new thread());
thread.start();
}
}
class thread implements Runnable{
@Override
public void run() {
synchronized(test.num){
for (int i = 0; i < 10000; ++i){
test.num++; //这里同样对对象进行了重新赋值,内存地址改变
}
System.out.println(test.num);
}
}
}
}