三个要素:
1:确定对象状态是由哪些变量构成。ps:如果一对象引用了其他对象,它的状态也包含了被引用对象的域。
2:确定限制状态变量的不便约束。
3:制定一个管理并发访问对象状态的策略。
实例限制:将数据封装到对象中,然后将对数据的访问限制在对象的方法上,更容易确保线程在访问数据时总能获得正确的锁。
励:
public class PersonSet{
private fina Set<Person>myset=new HashSet<Person>();
public synchronized void add Person(Person p)
{
myset.add(p);
}
public synchronized boolean containsPerson(Person p)
{
return mySet.contains(p);
}
}
该例子将hashset封装到类中,并同步访问该集合的方法,从而实现线程安全。看下面的俩程序:
public class BetterVector<E>extends Vector<E>{
public synchronized boolean putIfAbsent(E x){
boolean absent=!contains(x);
if(absent)
add(x);
return absent;
}
}
public class ListHelper<E>{
public list....同步列表
public sychronized boolean putIfAbsent(E x){
boolean absent=!lsit.contains(x);
if(absent)
list.add(x);
return absent;
}
}
第一个程序是正确的,而第二个程序是错误的。为什么呢,虽然该列表是同步的,方法也是同步的。但是锁只是对于方法进行了加锁,在条件判断的时候,其它的线程仍然能够对list进行操作。在该多个线程工作的时候该方法会失败。
应该使用如下加锁方式:
synchronized(list){
.........
}