ConcurrentHashMap并没有实现Lock-Free,只是使用了分离锁的办法使得能够支持多个writer开发,但是他需要更多的内存同样的思路用于更新数据库----乐观锁
public class SequenceDao {
public boolean compareAndSet(String name, int value, int expect) {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("name", name);
parameters.put("value", value);
parameters.put("expect", expect);
int updateCount = getSqlMapClientTemplate().update("seauence.compareAndSet", parameters);
return updateCount == 1;
}
}
public class SequenceService {
@Transactional(propagation = propagation.NOT_SUPPORTED)
public synchronized void intcrement(String sequenceName) {
for (;;) {
int value = dao.getValue(sequenceName);
if (dao.compareAndSet(sequenceName,value+1,value)) {
break;
}
}
}
}
使用悲观锁版本
public class SepuenceService {
SequenceDao dao = new SequenceDao();
@Transactional(propagation = Propagation.REQUIRED)
public synchronized void increment(String sequenceName) {
int value = dao.getValueForUpdate(sequenceName);
dao.set(sequenceName, value + 1);
}
}
public class SepuenceService {
SequenceDao dao = new SequenceDao();
@Transactional(propagation = Propagation.REQUIRED)
public synchronized void increment(String sequenceName) {
int value = dao.getValueForUpdate(sequenceName);
dao.set(sequenceName, value + 1);
}
}
注: lock-free 算法可以说是乐观锁,如果非激烈竟争的时候,不公使用锁
CopyOnWriteArrayList
public class EngLine {
private List<Listener> listeners = new ArrayList<Listener>();
public boolean addListener(Listener listener) {
synchronized (listener) {
return listeners.add(listener);
}
}
public void doxxx() {
synchronized (listeners) {
for (Listener listener : listeners) {
listener.hashCode();
}
}
}
}
public class EngLine2 {
//能够提高读操作时的效率
private List<Listener> listeners = new CopyOnWriteArrayList<Listener>();
public boolean addListener(Listener listener) {
synchronized (listener) {
return listeners.add(listener);
}
}
public void doxxx() {
synchronized (listeners) {
for (Listener listener : listeners) {
listener.hashCode();
}
}
}
}
锁的使用
1 使用支持CAS的数据结构,如:
ActionXXX ConcurrentMap CopyOnWriteList ConcurretLinkedQueue
2 一定要使用锁的时候,注意锁的顺序,相反顺序获得锁,就容易产生死锁
3 死锁经常是无法避免的,鸵鸟策略很多基础框架都采用
4 通过Dump线程的StackTrace,例如linux下执行kill -3<pid>
或者jstack -l<pid>
或者使用jconsole连接上去查看线程的StackTrace
5 外部锁常被忽视,例如数据库的锁