java Unsafe工具类提供了一个方法

public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

这个就是一个cas操作,原子操作。比较var1, 在var2偏移即offset位置的值是否为var4。如果是var4,更新为var5,返回true。否则,不做更新返回false

最近,听同事说了cas用到项目里面,感觉高大上。学习了一下,包装了一个cas整型操作

import java.lang.reflect.Field;
import sun.misc.Unsafe; /**
* @Author: <guanxianseng@163.com>
* @Description:
* @Date: Created in : 2018/11/28 3:36 PM
**/
public class GxfInteger {
private sun.misc.Unsafe U;
private long offset;
private Integer value = 0;
private static Object lock = new Object(); public GxfInteger(int value) throws Exception {
this.value = value;
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
U = (Unsafe) f.get(null);
offset = U.objectFieldOffset(GxfInteger.class.getDeclaredField("value"));
} public void increament(){
value ++;
} public void lockAdd(){
synchronized (lock){
value++;
}
} public void casIncreament(){
boolean update = false;
do{
update = U.compareAndSwapObject(this, offset, value, value + 1);
}while (!update);
} public int getValue() {
return value;
} public void setValue(int value) {
this.value = value;
}
}

写了一测试类

public class GxfIntegerTest {

  public static void main(String[] args) throws InterruptedException, Exception {
GxfInteger gxfInteger = new GxfInteger(0);
int threadNum = 100;
Runnable add = () -> {
for(int i = 0; i < 10000; i++){
// gxfInteger.increament();
gxfInteger.casIncreament();
// gxfInteger.lockAdd();
}
};
long start = System.currentTimeMillis(); Thread[] threads = new Thread[threadNum];
for(int i = 0; i < threads.length; i++){
threads[i] = new Thread(add);
}
for(int i = 0; i < threadNum; i++){
threads[i].start();
}
for(int i = 0; i < threadNum; i++){
threads[i].join();
}
System.out.println("time cost : " + (System.currentTimeMillis() - start));
// Thread.sleep(10000);
System.out.println("result: " + gxfInteger.getValue());
}
}

这里可以通过cas实现,线程安全。cas有点就是不会有锁的开销,上下文切换。也有缺点,自旋浪费资源,不能对多个资源保证线程安全

这里需要注意两点

1. 使用反射获取Unsafe对象

2. 注意offset的获取

Java自定义cas操作的更多相关文章

  1. 多线程之:java的CAS操作的相关信息

    一:锁机制存在的性能问题? 在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁(后面的章节还会谈到锁). 锁机制存在以下问题:(1)在多线程竞争下,加锁.释放锁会导 ...

  2. Java并发--Java中的CAS操作和实现原理

    版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/CringKong/article/deta ...

  3. java面试-CAS底层原理

    一.CAS是什么? 比较并交换,它是一条CPU并发原语. CAS是一种无锁算法,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B.当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什 ...

  4. 【Java并发编程实战】-----“J.U.C”:CAS操作

    CAS,即Compare and Swap,中文翻译为"比较并交换". 对于JUC包中,CAS理论是实现整个java并发包的基石.从整体来看,concurrent包的实现示意图如下 ...

  5. 深入浅出 Java Concurrency (5): 原子操作 part 4 CAS操作

    在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁(后面的章节还会谈到锁). 锁机制存在以下问题: (1)在多线程竞争下,加锁.释放锁会导致比较多的上下文切换和调度 ...

  6. Java乐观锁实现之CAS操作

    介绍CAS操作前,我们先简单看一下乐观锁 与 悲观锁这两个常见的锁概念. 悲观锁: 从Java多线程角度,存在着“可见性.原子性.有序性”三个问题,悲观锁就是假设在实际情况中存在着多线程对同一共享的竞 ...

  7. java高并发系列 - 第21天:java中的CAS操作,java并发的基石

    这是java高并发系列第21篇文章. 本文主要内容 从网站计数器实现中一步步引出CAS操作 介绍java中的CAS及CAS可能存在的问题 悲观锁和乐观锁的一些介绍及数据库乐观锁的一个常见示例 使用ja ...

  8. Java并发指南3:并发三大问题与volatile关键字,CAS操作

    本文转载自互联网,侵删   序言 先来看如下这个简单的Java类,该类中并没有使用任何的同步. 01 final class SetCheck { 02 private int  a = 0; 03 ...

  9. 并发系列2:Java并发的基石,volatile关键字、synchronized关键字、乐观锁CAS操作

    由并发大师Doug Lea操刀的并发包Concurrent是并发编程的重要包,而并发包的基石又是volatile关键字.synchronized关键字.乐观锁CAS操作这些基础.因此了解他们的原理对我 ...

随机推荐

  1. LOJ#2039. 「SHOI2015」激光发生器(计算几何)

    题面 传送门 题解 如果我初中科学老师知道我有一天计算的时候入射角不等于反射角不知道会不会把我抓起来打一顿-- 这题本质上就是个模拟,需要的芝士也就计蒜几盒的那点,不过注意细节很多,放到考场上只能看看 ...

  2. [CSS3] :nth-child的用法

    :nth-child(2)选取第几个标签,“2可以是你想要的数字” .demo01 li:nth-child(2){background:#090} :nth-child(n+4)选取大于等于4标签, ...

  3. 理解 atime,ctime,mtime (上)

    理解 atime,ctime,mtime (上) Unix文件系统会为每个文件存储大量时间戳.这意味着您可以使用这些时间戳来查找任意时间访问到的任何文件或目录(读取或写入),更改(文件访问权限更改)或 ...

  4. SpringMvc HttpMessageConverter之@ResponseBody

    我们先看HttpMessageConverter的示意图,从图片可以看出它是多么的重要.在一条必经之路截道了的感觉. 先上我的测试例子: jsp页面: <%@ page language=&qu ...

  5. Dota2App--第三天

    一.要实现的功能 1.新特性页面 1.1.是否进入新特性界面的两种情况 1)第一次安装此APP,进入新特性界面 2)不是第一次安装,但是有版本更新,进入新特性界面 1.2.具体的代码实现 //0.版本 ...

  6. Spring注入方式(1)

    Spring支持3种依赖注入方式,分别为属性注入.构造器注入和工厂方法注入(很少使用,不推荐),下面分别对属性注入和构造器注入详细讲解. 1.常量注入 属性注入是通过setter方法注入Bean的属性 ...

  7. 生成allure测试报告之后,服务器端口无法访问查看生成的report,可能是这样引起的。

    1. 检查防火墙 2. 如果机器有安装ADsafe,请关闭adsafe后重试

  8. [转] Java中Comparator进行对象排序

    [From] https://blog.51cto.com/thinklili/2063244 Java在8后引入了lambda表达式和流,使得排序方法有了变化 class User { int id ...

  9. Mac下使用Wine安装正则表达式工具RegexBuddy 4

    下载: (链接: https://pan.baidu.com/s/1bzRae6 密码: b5d3) 安装: 1.安装Wine 参考:http://www.cnblogs.com/EasonJim/p ...

  10. Linux下的Shell特殊符号大全(转)

    在shell中常用的特殊符号罗列如下: # ; ;; . , / \ 'string'| ! $ ${} $? $$ $* "string"* ** ? : ^ $# $@ `co ...