Java无锁队列的问题

圣诞老人123 2018-03-25 10:15:27
题目是实现一个无锁的Stack,并写一段测试代码(多线程访问),证明这个Stack是线程安全的。


public class TestCAS {

static LockFreeStack<Object> stack = new LockFreeStack<>();

static class Node<T> {
private T v;
private Node<T> next;

public Node(T value, Node<T> next){
v = value; this.next = next;
}
public void setNext(Node<T> next){
this.next = next;
}
public Node<T> getNext(){
return next;
}

public void setValue(T v){
this.v = v;
}

public T getValue(){
return v;
}
}

static class LockFreeStack<T>{
AtomicStampedReference<Node<T>> top = new AtomicStampedReference<>(null,0);
AtomicLong count = new AtomicLong(0);
public void push(T value){
Node<T> newvalue = new Node(value,null);
Node<T> oldvalue = null;
int stamp = 0;
do {
stamp = top.getStamp();
oldvalue = top.getReference();
newvalue.setNext(oldvalue);
} while(!top.compareAndSet(oldvalue,newvalue,stamp,stamp+1));
count.incrementAndGet();
System.out.println("count2:" + count.get());
}

public T pop(){
Node<T> newvalue = null;
Node<T> oldvalue = null;
int stamp = 0;
do {
stamp = top.getStamp();
oldvalue = top.getReference();
if(null == oldvalue){
continue;
}
newvalue = oldvalue.getNext();
} while(null == oldvalue || !top.compareAndSet(oldvalue,newvalue,stamp,stamp+1));
count.decrementAndGet();
System.out.println("count:"+count.get());
return oldvalue.getValue();
}

public void getCount(){
System.out.println("All:"+count.get());
}
}
static class Push extends Thread {
@Override
public void run() {
for(;;) {
stack.push("Random->"+Math.random());
Thread.yield();
}
}
}

static class Pop extends Thread {
@Override
public void run() {
for(;;) {
stack.pop();
Thread.yield();
//System.out.println("已出栈:" + stack.pop());
}
}
}

public static void main(String[] args) throws InterruptedException {
Push [] pushs = new Push[10];
Pop [] pop = new Pop[10];
for(int i = 0; i < 10; i++) {
pushs[i] = new Push();
pop[i] = new Pop();
}
for(int i = 0; i < 10; i++) {
pushs[i].start();
pop[i].start();
}

for (;;){
Thread.sleep(1000);
stack.getCount();
}

}
}


为什么count还会打印负数 求教
...全文
446 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
2018阿里巴巴中间件挑战赛-消息队列存储引擎题目设计基于Java.zip ### 使用的技术和环境 ### - 100% 原生Java Api (官方就是这么要求的...) - Maven 管理依赖和构件 - 运行环境在Linux系统下 ### 赛时的想法 ### - 使用mmap的方式读写数据文件 - 尽可能降低锁的粒度,甚至实现无锁化 - 鉴于测评程序产生的队列名前缀高度一致,采用了Trie字典树的修改版存储队列信息 - 每隔一定的间隔或符合一定的条件,会创建索引,并在文件中实现一个类似于链表的机制,遍历寻找索引记录 ### Benchmark ### 运行环境: - 阿里云天池平台 - 300GB SSD磁盘 - Linux操作系统 Deadline磁盘调度算法 - 每消息约 50 byte,累计约百万队列,20亿消息 运行成绩: - 线上跑分 63w TPS - 最高跑分 66w TPS (尝试了一下分bucket对数据进行操作,代码太乱,不放上来了) ### 赛后的反思 ### - 其实可以使用ByteBuffer先把数据读入缓冲区,然后再刷入磁盘,按块写入的效率会相对高些(利用操作系统DMA) - 读的时候其实需要考虑预读等优化,现在使用的暴力遍历读写太差劲了 - 索引做得不是很好,读索引时,随机读写太多,当队列增多时,读索引的时间会大幅增多 - 还有好多好多的优化点和可以进步的地方~ **P.S.** start.sh是一个模拟测评程序的脚本,可以在Linux系统+SSD磁盘下测试使用
container Collection 标记: 顶级接口 List 标记: interface ArrayList 标记: class CRUD : boolean add​(E e) boolean remove​(Object o) E set​(int index, E element) E get​(int index) 底层数组实现,查询快,增删慢 LinkedList 标记: class CRUD : boolean add​(E e) E get​(int index) 底层为链表,增删快,查询快 Vector 标记: class 底层数组实现,线程安全,速度太慢,没用 CopyOnWriteArrayList 标记: class Set 标记: interface HashSet 标记: class CRUD : boolean add​(E e) boolean remove​(Object o) 底层哈希表,基于hashCode的equals的比较方式,线程不安全,存取速度快。 SortedSet 标记: interface TreeSet 标记: class 实现comparable接口,元素是以二叉树的形式存放的。线程不安全 CopyOnWriteArraySet 标记: class Queue 标记: interface BlockingQueue 标记: interface ArrayBlockingQueue LinkedBlockingQueue ConcurrentLinkedQueue 标记: class Map 标记: 顶级接口 HashMap 标记: class V get​(Object key) V put​(K key, V value) Set keySet​() Set> entrySet​() 线程不安全,速度快,允许存放null键,null值。 SortedMap 标记: class TreeMap 对键进行排序 HashTable 标记: class Properties 标记: class 线程安全,速度慢,不允许存放null键,null值,已被HashMap替代。 Collections 标记: 均以synchronized实现, 性能没用提高 synchronizedCollection synchronizedList synchronizedSet synchronizedMap synchronizedSortedSet synchronizedSortedSet JUC CopyOnWriteArrayList 写有锁,读无锁,读写之间不阻塞,优于读写锁 写入时先copy一个容器副本,再添加新元素,最后替换引用 copy的容器副本过大时,速度慢,不易使用 CopyOnWriteArraySet 底层使用CopyOnWriteArrayList实现 使用addIfAbsent()添加元素时,会遍历数组,如果存在元素,则抛弃副本 ConcurrentHashMap 初始容量默认为16段(segment),使用分段锁设计 ConcurrentLinkedQueue 高并发下性能最好的队列 无锁,采用CAS比较算法,核心参数(V,E,N) V:要更新的变量 E:预期值 N:新值 只有当V==E时,V=N;否则表示已被更新过,则取消当前操作 阻塞队列 BlockingQueue接口 void put(E e) 将指定元素插入此队列,如果没有可用空间,则等待 E take()获取并移除此队列头部元素,如果没有可用元素,则等待 ArrayBlockingQueue 数组结构实现,有界队列,手工固定上限 LinkedBlockingQueue 链表结构实现,无界队列(默认上限Integer.MAX_VALUE)

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧