ConcurrentHashMap并没有实现Lock-Free,只是使用了分离锁的办法使得能够支持多个writer开发,但是他需要更多的内存同样的思路用于更新数据库----乐观锁
publicclassSequenceDao{
publicbooleancompareAndSet(Stringname,intvalue,intexpect){
Map<String,Object>parameters=newHashMap<String,Object>();
parameters.put("name",name);
parameters.put("value",value);
parameters.put("expect",expect);
intupdateCount=getSqlMapClientTemplate().update("seauence.compareAndSet",parameters);
returnupdateCount==1;
}
}
publicclassSequenceService{
@Transactional(propagation=propagation.NOT_SUPPORTED)
publicsynchronizedvoidintcrement(StringsequenceName){
for(;;){
intvalue=dao.getValue(sequenceName);
if(dao.compareAndSet(sequenceName,value+1,value)){
break;
}
}
}
}
使用悲观锁版本
publicclassSepuenceService{
SequenceDaodao=newSequenceDao();
@Transactional(propagation=Propagation.REQUIRED)
publicsynchronizedvoidincrement(StringsequenceName){
intvalue=dao.getValueForUpdate(sequenceName);
dao.set(sequenceName,value+1);
}
}
publicclassSepuenceService{
SequenceDaodao=newSequenceDao();
@Transactional(propagation=Propagation.REQUIRED)
publicsynchronizedvoidincrement(StringsequenceName){
intvalue=dao.getValueForUpdate(sequenceName);
dao.set(sequenceName,value+1);
}
}
注:lock-free算法可以说是乐观锁,如果非激烈竟争的时候,不公使用锁
CopyOnWriteArrayList
publicclassEngLine{
privateList<Listener>listeners=newArrayList<Listener>();
publicbooleanaddListener(Listenerlistener){
synchronized(listener){
returnlisteners.add(listener);
}
}
publicvoiddoxxx(){
synchronized(listeners){
for(Listenerlistener:listeners){
listener.hashCode();
}
}
}
}
publicclassEngLine2{
//能够提高读操作时的效率
privateList<Listener>listeners=newCopyOnWriteArrayList<Listener>();
publicbooleanaddListener(Listenerlistener){
synchronized(listener){
returnlisteners.add(listener);
}
}
publicvoiddoxxx(){
synchronized(listeners){
for(Listenerlistener:listeners){
listener.hashCode();
}
}
}
}
锁的使用
1使用支持CAS的数据结构,如:
ActionXXXConcurrentMapCopyOnWriteListConcurretLinkedQueue
2一定要使用锁的时候,注意锁的顺序,相反顺序获得锁,就容易产生死锁
3死锁经常是无法避免的,鸵鸟策略很多基础框架都采用
4通过Dump线程的StackTrace,例如linux下执行kill-3<pid>
或者jstack-l<pid>
或者使用jconsole连接上去查看线程的StackTrace
5外部锁常被忽视,例如数据库的锁