示例代码:
public class SyncTest {
private List<String> list= new ArrayList<String>();
public void syncAddPrint(){
synchronized(list){
for(int i = 0; i < 10; i++) {
list.add(""+ i);
System.out.println(list);
}
}
}
public void syncAdd2(){
synchronized(list){
list.add("A");
list.add("B");
list.add("C");
}
}
public void noSyncAdd() {
list.add("X");
list.add("Y");
list.add("Z");
}
public void noSyncNew(){
list= new ArrayList<String>();
list.add("Ha");
list.add("Ha");
list.add("Ha");
}
public static void main(String[] args){
final SyncTest test =new SyncTest();
Thread thread1 = new Thread() {
public void run() {
test.syncAddPrint();
}
};
thread1.start();
Thread thread2 = new Thread() {
public voidrun() {
test.syncAdd2();
}
};
thread2.start();
Thread thread3 = new Thread() {
public voidrun() {
test.noSyncAdd();
}
};
thread3.start();
Thread thread4 = new Thread() {
public voidrun() {
test.noSyncNew();
}
};
thread4.start();
}
}
输出结果可能是:
[0]
[0,1]
[0, 1,2]
[0, 1, 2,X, 3]
[0, 1, 2,X, 3, Y, 4]
[Ha, 5]
[Ha, 5,Z, 6]
[Ha, 5,Z, 6, Ha, Ha, 7]
[Ha, 5,Z, 6, Ha, Ha, 7, 8]
[Ha, 5,Z, 6, Ha, Ha, 7, 8, 9]
在thread1执行方法syncAddPrint的过程中,thread1获得了锁list。
若thread1获得锁list未释放,线程thread2执行syncAdd2,但是得不到锁list,故而被阻塞。
thread3执行noSyncAdd,不需要获得锁list,所以在方法中轻易将锁list的元素改变。
thread4执行noSyncNew,不需要获得锁list,所以在方法中轻易将锁list替换成另一个对象。
而thread3、thread4这些对锁list的改变动作都是在thread1还持有锁list的情况下发生的。
由此可见,要保证锁list在被某线程持有的情况下不被改变,则必须访问锁list的所有代码块都必须使用synchronized(list)才可以,一旦某个方法遗漏,则不可保证。