JUC并发编程十 并发架构--Unsafe_并发编程 unsafe-程序员宅基地

技术标签: java  

Unsafe提供了非常底层的,操作内存,线程的方法.Unsafe对象不能直接调用,只能通过反射获得.

import lombok.Data;
import sun.misc.Unsafe;

import java.lang.reflect.Field;

public class TestUnsafe {
    
    public static void main(String[] args) throws Exception {
    
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        Unsafe unsafe = (Unsafe)theUnsafe.get(null);
        System.out.println(unsafe);

        // 1. 获取域的偏移地址
        long idOffset = unsafe.objectFieldOffset(Student.class.getDeclaredField("id"));
        long nameOffset = unsafe.objectFieldOffset(Student.class.getDeclaredField("name"));

        Student student = new Student();
        System.out.println(student);

        // 2. 执行cas操作
        unsafe.compareAndSwapInt(student,idOffset,0,1);
        unsafe.compareAndSwapObject(student,nameOffset,null,"小明");

        // 3.  验证
        System.out.println(student);
    }
}

@Data
class Student{
    
    volatile int id;
    volatile String name;
}

使用Unsafe构建自己的原子类

import sun.misc.Unsafe;

import java.util.ArrayList;
import java.util.List;

public class TestMyAtomicInteger {
    
    public static void main(String[] args) {
    
        Account.demo(new MyAtomicInteger(10000));
    }
}

class MyAtomicInteger implements Account{
    
    private volatile int value;  // 使用cas,必须是volatile
    private static final long valueOffset; // 获取域的偏移量
    private static final Unsafe UNSAFE;

    static{
    
        UNSAFE = UnsafeAccessor.getUnsafe();

        try {
    
            valueOffset = UNSAFE.objectFieldOffset(MyAtomicInteger.class.getDeclaredField("value"));
        } catch (NoSuchFieldException e) {
    
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public int getValue(){
    
        return value;
    }

    public void decrement(int amount){
    
        while(true){
    
            int prev = this.value;
            int next = prev - amount;
            if(UNSAFE.compareAndSwapInt(this,valueOffset,prev,next)){
    
                break;
            }
        }
    }


    public MyAtomicInteger(int value){
    
        this.value = value;
    }

    @Override
    public int getBalance() {
    
        return value;
    }

    @Override
    public void withdraw(int amount) {
    
        decrement(amount);
    }
}


interface Account{
    
    // 设置余额
    int getBalance();

    void withdraw(int amount);

    static void demo(Account account){
    
        List<Thread> ts = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
    
            // 创建1000个线程,每个线程减去10
            ts.add(new Thread(()->{
    
                account.withdraw(10);
            }));
        }

        ts.forEach(Thread::start);
        ts.forEach(t->{
    
            try {
    
                t.join();
            } catch (InterruptedException e) {
    
                e.printStackTrace();
            }
        });

        System.out.println(account.getBalance());
    }
}
import sun.misc.Unsafe;

import java.lang.reflect.Field;

public class UnsafeAccessor {
    
    private static final Unsafe unsafe;
    static{
    
        try {
    
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            unsafe = (Unsafe)theUnsafe.get(null);
        } catch (Exception e) {
    
            throw new Error(e);
        }
    }

    public static Unsafe getUnsafe(){
    
        return unsafe;
    }
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_37564426/article/details/122157357

智能推荐

创建物理卷报错Can't open /dev/sdb5 exclusively. Mounted filesystem的问题解决过程记录..._虚拟机中将分区转化为物理卷时,提示can't open怎么解决-程序员宅基地

文章浏览阅读7.3k次。yum服务器lvm扩容,data目录是yum存放rpm包的目录,只有20G,需要添加磁盘扩容到80G# df -lhFilesystem Size Used Avail Use% Mounted on/dev/mapper/vg_node5-root 20G 479M 18G 3% /tmpfs ..._虚拟机中将分区转化为物理卷时,提示can't open怎么解决

python_opencv点击鼠标获取图像中坐标值_opencv返回图片坐标-程序员宅基地

文章浏览阅读1.7k次。python_opencv使用鼠标获取图片的某一点坐标@[TOC]https://blog.csdn.net/jiangkui007/article/details/82866755_opencv返回图片坐标

在Python应用中使用MongoDB-程序员宅基地

文章浏览阅读67次。翻译:j_hao104原文:Introduction to MongoDB and Python 在这篇文章中,将向您展示如何使用Python链接目前主流的MongoDB(V3.4.0)数据库,主要使用PyMongo(v3.4.0)和MongoEngine(V0.10.7)。同时比..._python3.10支持mongo3.4吗

iOS自动化布局-AutoLayout约束优先级_ios auto layout priority-程序员宅基地

文章浏览阅读2k次。约束的优先级AutoLayout添加的约束中也有优先级(Priority),优先级的数值1~1000,分为两种情况:一种情况是我们经常添加的各种约束,默认值1000(最大值)优先执行,条件允许的话系统会自动满足我们的约束需求。第二种就是固有约束(intinsic content size)严格说这种更像UILabel和UIButton的一种属性,但是在Autolayout中需要满足属性取值..._ios auto layout priority

海洋元宇宙Aquqnee,给人们全新游戏体验_aquanee链游怎么玩-程序员宅基地

文章浏览阅读169次。游戏(Game)+金融(Finance)是GameFi最早时期在加密领域外的结合形式,当 GameFi 这个词来到加密领域,由于DEFI生态的成熟,它所指的已经不仅仅是Game+Finance,更是指“Game+DeFi”。而GameFi赛道也在2021年底迎来了爆发,随着元宇宙与NFT概念的爆火,GameFi也一扫早期加密猫“粗制滥造”固有印象的阴霾,从体验感以及即玩即赚等方向,都给予了玩家不一样的体验,例如最近大火的项目GMT,通过购买官方的跑步鞋NFT,然后参与到游戏中来,GMT市值也一度大._aquanee链游怎么玩

何恺明:重新思考ImageNet预训练模型_vgg16top1 74% 如何训练的-程序员宅基地

文章浏览阅读1.9k次,点赞2次,收藏7次。参考文章:https://mp.weixin.qq.com/s/XM1AEBVleaOe9LNe4cDaxg论文:《Rethinking ImageNet Pre-training》总结:(1)当数据量较少时,建议使用预训练模型,这样可以快速收敛,而且可以得到较好的精度;(2)数据量足够的情况下,预训练模型相比随机初始化可以更快收敛,但不能带来精度的提高。..._vgg16top1 74% 如何训练的

随便推点

linux的vi正则表达式,教你如何轻松搞定Linux正则表达式-程序员宅基地

文章浏览阅读181次。描述正则表达式是一种字符模式,用于在查找过程中匹配制定的字符。元字符通常在Linux中分为两类:Shell元字符,由Linux Shell进行解析;正则表达式元字符,由vi/grep/sed/awk等文本处理工具进行解析;正则表达式一般以文本行进行处理,在进行下面实例之前,先为grep命令设置--color参数:这样每次过滤出来的字符串都会带色彩了。在开始之前还需要做一件事情,就是创建一个测试用的..._linux vi正则

Vue在线编译器:vue-running_在线vue编译-程序员宅基地

文章浏览阅读1.1w次,点赞2次,收藏9次。现在网络上,有非常多的JS在线编译器,非常好用,特备是在调试某些片段代码的时候,比在本地重新新建文件来的方便快捷~ 非常流行的比如 JS.do、 jsfiddle、JSRUN 等等。而对于Vue来说,在线编译器有时候会显得更加必要,因为初始化一个Vue项目还是需要花一点时间的~并且需要安卓很多的依赖,费时费力。现在也有很多JS在线编译器已经支持Vue代码了,另外..._在线vue编译

poj 动态规划题目列表及总结_poj 动态规划 题集-程序员宅基地

文章浏览阅读1.5w次,点赞17次,收藏40次。此文转载别人,希望自己能够做完这些题目!1.POJ动态规划题目列表 容易:1018, 1050, 1083, 1088, 1125, 1143, 1157, 1163, 1178, 1179, 1189, 1208, 1276,1322, 1414, 1456, 1458, 1609, 1644, 1664, 1690, 1699, 1740(博弈),1742,_poj 动态规划 题集

第三次作业-用scala写一个wordcount程序_scala编写wordcount程序-程序员宅基地

文章浏览阅读240次。第一:用scala写一个wordcount程序***package com.scala.wordcountobject wordcountApp {def main(args: Array[String]): Unit = {//造一个List,模拟读取文件val wordlist= List(&amp;amp;amp;quot;hello scala&amp;amp;amp;quot;,&amp;amp;amp;quot;hello word&amp_scala编写wordcount程序

eclipse/MyEclipse代码模板XML配置文件分享,爽爆了~_semyxml-程序员宅基地

文章浏览阅读337次。<?xml version="1.0" encoding="UTF-8" standalone="no"?><templates><template autoinsert="true" context="delegatecomment_context" deleted="false" description="Comment for delegate methods" enabled="true" id="org.eclipse.jdt.ui.text.codetemplate_semyxml

oracle 查询关键字,Oracle 中的SELECT 关键字(查询、检索)-程序员宅基地

文章浏览阅读1k次。1. SELECT 关键字用法:检索单个列:select 列名 from 表名;例:select ename from emp;检索多个列: select [列1,列2, ... ,列N] from 表名;例:select ename , sal from emp;检索所有列:select * from 表名;例:select * from emp;2. 通配符(A):* :代表0个或多个列_ :..._oracle中 select 字段加.的用法

推荐文章

热门文章

相关标签