版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013276277/article/details/81450210
大家都知道java中的同步容器类是线程安全的,但是在某些情况下可能需要额外的客户端加锁来保护复合操作。容器上的常见的复合操作是:迭代(遍历完容器中的所有容器),跳转(根据指定顺序找到当前元素的下一个个元素)以及条件运算 。最常见的例如”若没有则添加“(检查map中是否存在key值,不存在再添加)。
在同步容器类中,这些复合操作在没有客户端加锁的情况下仍然是线程安全的,但当其他线程并发地修改容器时,他们可能出现意料之外的行为。
例如以下vector的getLast和setLast操作。虽然大家都知道vector是线程安全的,但是在VectorDemo中getLast不是线程安全的,因为list.size()和list,get()这两个对list的操作不能保证他们俩的原子性,list.size()的结果在执行list.get()时可能已经发生状态了(被其他线程对list的remove所破坏)。让其变成线程安全的办法就是注释里的内容,就是锁住list。
package com.zy.charter5;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
public class VectorDemo {
public static Object getLast(Vector list) {
int lastIndex = list.size() - 1;
return list.get(lastIndex);
}
// public static Object getLast(Vector list) {
// synchronized (list) {
// int lastIndex = list.size() - 1;
// return list.get(lastIndex);
// }
// }
public static void print(Vector list) {
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
class Student {
private String name;
Student(String name) {
this.setName(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
上述的加锁方式是会存在死锁现象的,这个留在之后的章节进行介绍。