关于多线程并发,该采用Lock还是Free,其实这都是各有弊端的。
相比于Lock,CAS 原语在轻度和中度争用情况下确实可以大幅度提高程序性能。
但CAS的弊端同时也在限制,CAS 的原子性完全取决于硬件实现。大多数 Intel 和 AMD 的 CPU 采用了一种叫做 MOSEI 缓存一致性协议来管理缓存。这种架构下,处理器缓存内 CAS 操作相对成本低廉。但一旦资源争用,就会引起缓存失效和总线占用。缓存越失效,总线越被占用,完成 CAS 操作也越被延迟。缓存争用是程序可伸缩性杀手。当然对于非 CAS 内存操作来说也是如此,但 CAS 情况更加槽糕。同时CAS 操作要比普通内存操作花费更多 CPU 周期。这归功于缓存分级的额外负担、刷新写缓冲区与穿越内存栅栏限制和需求以及编译器对 CAS 操作优化的能力。
CAS这是由硬件提供原子操作指令实现的。在非激烈竞争的情况下,开销更小,速度更快。java.util.concurrent中实现的原子操作类包括:AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference
看一下Java的Lock-Free算法
采用synchronized关键字实现
class Counter
{
private volatile int max = 0;
//若要线程安全,需要加锁
public synchronized void set(int value)
{
if (value > max)
{
max = value;
}
}
public int getMax()
{
return max;
}
}
采用CAS原子指令实现
class Counter
{
private AtomicInteger max = new AtomicInteger();
// LockFree算法,不需要加锁。通常都是三个部分组成:① 循环 ② CAS (CompareAndSet) ③ 回退
public void set(int value)
{
for (;;)
{
int current = max.get();
if (value > current)
{
if (max.compareAndSet(current, value))
{
break;
} else
{
continue;
}
} else
{
break;
}
}
}
public int getMax()
{
return max.get();
}
}
进一步使用Lock-Free数据结构
class BeanManager
{
/*
* ConcurrentHashMap并没有实现Lock-Free,只是使用了
* 分离锁(锁由数据结构来管理)的办 法使得能够支持多个Writer并发。
* ConcurrentHashMap需要使用更 多的内存。
*/
private ConcurrentMap<String, Object> map = new ConcurrentHashMap<String, Object>();
public Object getBean(String key)
{
Object bean = map.get(key);
if (bean == null)
{
map.putIfAbsent(key, createBean());
bean = map.get(key);
}
return bean;
}
private Object createBean()
{
return new Integer((int) Math.random() * 1000);
}
}
ConcurrentHashMap功能规范和HashTable一样,关于ConcurrentHashMap的详细介绍
http://hill007299.iteye.com/blog/1490779
① 使用支持CAS的数据结构,避免使用锁,如:AtomicXXX、ConcurrentMap、CopyOnWriteList、ConcurrentLinkedQueue
② 一定要使用锁的时候,注意获得锁的顺序,相反顺序获得锁,就容易产生死锁。
③ 死锁经常是无法完全避免的,鸵鸟策略被很多基础框架所采用。
④ 通过Dump线程的StackTrace,例如linux下执行命令kill -3 <pid>,或者jstack –l <pid>,或者使用Jconsole连接上去查看线程的StackTrace,由此来诊断死锁问题。
⑤ 外部锁常被忽视而导致死锁,例如数据库的锁
⑥ 存在检测死锁的办法
⑦ 存在一些预防死锁的手段,比如Lock的tryLock,JDK 7中引入的Phaser等。
对于CAS,同样的思路用于更新数据库-乐观锁,先比与悲观锁不需要使用锁,从而开销更小,速度更快。在这里对于乐观锁和悲观锁就不多讲了

本文探讨了并发编程中Lock与CAS的选择与应用。详细对比了两种方式在不同场景下的性能表现,并通过Java代码示例介绍了如何使用CAS实现无锁算法。
665

被折叠的 条评论
为什么被折叠?



