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. 丢用lamp手动安装apache php mysql

    Centos7环境下. 使用lamp环境无法正常显示出thinkphp站点的内容,一气之下,选择手动安装 第一步: 安装apache  php 和php连接数据库的工具php-mysql [root@ ...

  2. mysql 与sqlser group by

    mysql select * ,count(1)  from simccbillm18 group by MonthNum; SqlSer select  col1,col2 from table g ...

  3. MDX常用几种查询对比

    MDX1: SELECT NON EMPTY {Hierarchize( { [Measures].[年初数 的总和], [Measures].[期末数 的总和], [Measures].[本期发生数 ...

  4. CentOS7 安装 Adobe Flash 看网络视频

    登录 Adobe 网站,找到 Adobe Flash Player 下载页,进入后网页自动识别 Linux 环境,手动选择版本,选择 YUM 方式,自动下载一个 rpm 文件 定位到下载目录,通常默认 ...

  5. linux MD5 SHA1 等 文件校验方法

    为解决官方发布的软件包被别人更改或者软件在传输过程中出现传输错误等问题,软件官方在提供软件包的同时,还提供一个保存MD5校验码的文件. Linux/unix中可以使用 md5sum 文件名 sha1s ...

  6. redis持久化之 aof日志

    aof就是把执行的命令写到文本文件里面 aof使用过程 第一步: 修改配置文件,并启动server 第二步, 当前目录下面会生成一个 appendonly.aof文件,但是是空的 去客户端 开始操作后 ...

  7. LINUX 查找替换命令 总结

    find /var/ -name "*.php" > /home/tmp 在/var/目录下查找 所有以.php后缀结尾的文件  结果很多,就 > 输出结果到/home ...

  8. IO流(二)字符流

    1.字符流:在字节流的基础上添加了编码机制.很大程度上和字节流操作一样的,字符流只能操作文本类文件,准确的说应该是纯文本类文件.例如.txt,.java,.cpp,.html等 编码:每一个国家都有自 ...

  9. nginx图片处理笔记(http-image-filter-module、lua)

    实验环境:CentOS 6.10 目标:1.使用http-image-filter-module进行图片变换:2.使用lua进行格式转换: 安装EPEL https://fedoraproject.o ...

  10. Javac源码解读-书目录

    1.Javac编译器 (1)Javac编译器介绍(主要介绍如何从java源代码到class的一个转换过程) (2)Javac的源码(说明其中哪个功能由哪个主要的类来完成) (3)Javac支持的命令及 ...