 
对象管制
例子1:
| 1
2
3
4
5
6
 | @ThreadSafe
public class PersonSet {
  private final Set<Person> mySet = new HashSet<>();
  public synchronized void addPerson(Person p) { ... }
  public synchronized boolean containsPerson(Person p) { ... }
}
 | 
 
例子2:
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
 | @ThreadSafe
public class PersonSet {
  private final Set<Person> mySet = new HashSet<>();
  private final Object mylock = new Object();
  public void addPerson(Person p) {
    synchronized(mylock) {
      ...
    }
  }
}
 | 
 
例子3:
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
 | @TreadSafe
public class MonitorVehicleTracker {
  private final Map<String, MutablePoint> locations;
  public MonitorVehicleTracker(Map<String, MutablePoint> locations) {
    // 深copyMap,防止MutablePoint被共享
    this.locations = deepCopy(locations);
  }
  public synchronized Map<String, MutablePoint> getLocations() {
    // 深copyMap,防止MutablePoint逃逸
    return deepCopy(this.locations);
  }
  // 用monitor lock保护访问
  public synchronized void setLocation(String id, int x, int y) { ... }
}
 | 
 
代理线程安全
把线程安全的工作代理给其他能提供线程安全的类:
例子:
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
 | @ThreadSafe class DelegatingVehicleTracker {
  private final ConcurrentMap<String, ImmutablePoint> locations;
  private final Map<String, ImmutablePoint> unmodifiableMap;
  public DelegatingVehicleTracker(Map<String, ImmutablePoint> points) {
    // 把Map浅copy过来
    locations = new ConcurrentHashMap<>(points);
    // 这个比较妙,把线程安全代理给了并发Map
    unmodifiableMap = Collections.unmodifiableMap(locations);
  }
  // 就算逃逸出去也无所谓,反正只能只读,而且因为底层是并发Map,所以不用担心可见性、原子性等问题
  public Map<String, MutablePoint> getLocations() {
    return unmodifiableMap;
  }
  public void setLocation(String id, int x, int y) {
    locations.put(...)
  }
}
 | 
 
给线程安全类添加功能
给线程安全的类添加功能的时候要注意不要破坏线程安全。
客户方加锁
下面就是个反面例子:
| 1
2
3
4
 | public class ListHelper {
  public List list = Collections.synchronizedList(new ArrayList());
  public synchronized boolean putIfAbsent(Object v) { ... }
}
 | 
 
这是因为putIfAbsent使用的monitor lock和synchronizedList自身使用的monitor lock不是同一个,这就破坏了线程安全。
正确的做法:
| 1
2
3
4
5
6
7
8
 | public class ListHelper {
  public List list = Collections.synchronizedList(new ArrayList());
  public boolean putIfAbsent(Object v) {
    synchronized (list) {
      ...
    }
  }
}
 | 
 
组合
可以这么干:
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 | public class ImprovedList implents List {
  private final List list;
  public synchronized boolean putIfAbsent(Object v) {
    ...
    list.add(v);
  }
  public synchronized void clear() {
    list.clear();
  }
  ...
}
 | 
 
评论