CAS 原理 应用
- 原子CAS操作
原子操作指令里,有原子加,原子减,cas到底是什么呢?
首先看一段代码,
bool compare_and_swap(int *accum, int *dest, int newval)
{
if (*accum == *dest) {
*dest = newval;
return true;
} else {
*accum = *dest;
return false;
}
}
cas即是Compare-and-swap,先比较再互换,即修改,意思就是,当reg等oldvalue的时候,将reg设置为newval,这段代码在非原子情况下(多线程)是没用的.
CAS操作,到底有什么威力?
如果要修改一个变量,在多线程下,应该要加锁,代码是这样的
int num = 0;
void add()
{
lock();
num = num + 123;
unlock();
}
但是如果不要锁,cas来操作??
int num = 0;
void add()
{
int temp;
do
{
temp = num;
}
while (cas(num, temp, temp+123)==true)
}
先让temp目的值=num实际值,如何这个过程中num的值没有改变(temp==num值)则,将新值temp=123 复制给num,跳出循环;
如何第一次发生了变化,那么在读read一次num的值给temp,再次cas比较
- 2=.研究 cmpxchg指令
cmpxchg是汇编指令
作用:比较并交换操作数.
如:CMPXCHG r/m, r
==> cmpxchg (目的操作数, 源操作数,RAX寄存器)
将累加器AL/AX/EAX/RAX中的值与首操作数(目的操作数)比较,如果相等,第2操作数(源操作数)的值装载到首操作数,zf置1。
如果不等, 首操作数的值装载到AL/AX/EAX/RAX并将zf清0
#include<iostream>
using namespace std;
int main(){
int a=0,b=0,c=0; __asm{
mov eax,100;
mov a,eax
}
cout << "a := " << a << endl;
b = 99;
c = 11;
__asm{
mov ebx,b
cmpxchg c,ebx //将累加器EAX中的值与首操作数(目的操作数)c=11比较 eax=100 != c=11,即不相等,eax=c;
mov a,eax
}
cout << "b := " << b << endl;
cout << "c := " << c << endl;
cout << "a := " << a << endl;
return 0;
}
输出:(如果不等, "首操作数"(c)的值装载到AL/AX/EAX/RAX并将zf清0)
a := 100
b := 99
c := 11
a := 11
#include<iostream>
using namespace std;
int main(){
int a=0,b=0,c=0; __asm{
mov eax,100;
mov a,eax
}
cout << "a := " << a << endl;
b = 99;
c = 99;
__asm{
mov eax,99
mov ebx,777
cmpxchg c,ebx //将累加器EAX=99中的值与首操作数(目的操作数)c=99比较,相等,第2操作数(源操作数)ebx的值装载到首操作数c(c=ebx=777),zf置1。
mov a,eax
}
cout << "b := " << b << endl;
cout << "c := " << c << endl;
cout << "a := " << a << endl;
return 0;
}
输出:(如果相等,第2操作数(源操作数)的值装载到首操作数,zf置1)
a := 100
b := 99
c := 777
a := 99
3=.多线程编程中如何解决数据安全的问题?
package com.tedu;
import java.util.concurrent.atomic.AtomicInteger;
public class MoneyRunnable implements Runnable {
private AtomicInteger sumMoney= new AtomicInteger(100);
@Override
public void run() {
while (true){
Data.lock.lock();
if(sumMoney.get()>0){
System.out.println(Thread.currentThread().getName() + "获得一元钱");
if (Thread.currentThread().getName().equals("张三")) {
Data.zsMoney++;
} else if (Thread.currentThread().getName().equals("李四")) {
Data.lsMoney++;
} else {
Data.wwMoney++;
}
sumMoney.decrementAndGet();
System.out.println(sumMoney.get());
}else {
System.out.println("钱抢完了");
System.out.println("张三获得了:" + Data.zsMoney);
System.out.println("李四获得了:" + Data.lsMoney);
System.out.println("王五获得了:" + Data.wwMoney);
System.out.println("他们一共获得了:"+(Data.zsMoney+Data.wwMoney+Data.lsMoney));
break;
}
try {
Thread.sleep(400);
}catch (Exception e){e.printStackTrace();}
Data.lock.unlock();
}
}
}
package com.tedu; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class Data {
public static int zsMoney=0; //张三zs
public static int lsMoney=0;//李四
public static int wwMoney=0;//王五 public static int zsMoneyHitNum=0;
public static int lsHitNum=0;
public static int wwHitNum=0; public static Object lockObject1= new Data();
public static Object lockObject2=new Data();
public static Lock lock = new ReentrantLock();
}
package com.tedu;
public class MainApp {
public static void main(String[] args) {
MoneyRunnable my1 = new MoneyRunnable();
Thread t1 = new Thread(my1);
Thread t2= new Thread(my1);
Thread t3 = new Thread(my1);
t1.setName("张三");
t2.setName("李四");
t3.setName("王五");
t1.start();
t2.start();
t3.start();
}
}
这个用sychronized的,和lock的用法一样
while (true) {
/**
* 同步代码块实现数据安全:
*
* 这里面的this就是一把锁,使用这个类创建的线程使用同一把锁
*
*/
synchronized (this) {
if (sumMoney > 0) {
/**
* sumMoney = sumMoney - 1; 放在前面就不会有问题
*/
// sumMoney = sumMoney - 1;
System.out.println(Thread.currentThread().getName() + "获得一元钱");
if (Thread.currentThread().getName().equals("张三")) {
Data.zsMoney++;
} else if (Thread.currentThread().getName().equals("李四")) {
Data.lsMoney++;
} else {
Data.wwMoney++;
}
/**
* sumMoney = sumMoney - 1; 放在后面就会出现数据安全问题(线程安全问题)
*/
sumMoney = sumMoney - 1;
} else {
System.out.println("钱分完了:");
System.out.println("张三获得了:" + Data.zsMoney);
System.out.println("李四获得了:" + Data.lsMoney);
System.out.println("王五获得了:" + Data.wwMoney);
System.out.println("他们一共获得了:" + (Data.zsMoney + Data.wwMoney + Data.lsMoney));
try {
// 防止数据刷的过快,休眠一段时间
Thread.sleep(4000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
atzhang
CAS 原理 应用的更多相关文章
- 采用CAS原理构建单点登录
企业的信息化过程是一个循序渐进的过程,在企业各个业务网站逐步建设的过程中,根据各种业务信息水平的需要构建了相应的应用系统,由于这些应用系统一般是在不同的时期开发完成的,各应用系统由于功能侧重.设计方法 ...
- JAVA CAS原理深度分析-转载
参考文档: http://www.blogjava.net/xylz/archive/2010/07/04/325206.html http://blog.hesey.net/2011/09/reso ...
- JAVA CAS原理
转自: http://blog.csdn.net/hsuxu/article/details/9467651 CAS CAS: Compare and Swap java.util.concurren ...
- 【转】JAVA CAS原理深度分析
java.util.concurrent包完全建立在CAS之上的,没有CAS就不会有此包.可见CAS的重要性. CAS CAS:Compare and Swap, 翻译成比较并交换. java.uti ...
- JAVA CAS原理深度分析
参考文档: http://www.blogjava.net/xylz/archive/2010/07/04/325206.html http://blog.hesey.net/2011/09/reso ...
- CAS原理与协议
SSO英文全称Single Sign On,单点登录. SSO是在多个应用系统中,用户仅仅须要登录一次就能够訪问全部相互信任的应用系统. SSO的解决方式非常多,比方收费的有UTrust.惠普灵动等, ...
- JAVA CAS原理深度分析(转)
看了一堆文章,终于把JAVA CAS的原理深入分析清楚了. 感谢GOOGLE强大的搜索,借此挖苦下百度,依靠百度什么都学习不到! 参考文档: http://www.blogjava.net/xylz/ ...
- Java中的CAS原理
前言:在对AQS框架进行分析的过程中发现了很多CAS操作,因此有必要对CAS进行一个梳理,也便更清楚的了解其原理. 1.CAS是什么 CAS,是compare and swap的缩写,中文含义:比较交 ...
- JAVA CAS原理浅谈
java.util.concurrent包完全建立在CAS之上的,没有CAS就不会有此包.可见CAS的重要性. CAS CAS:Compare and Swap, 翻译成比较并交换. java.uti ...
- CAS 原理
基础模式 1. 访问服务: 客户端发送请求访问应用系统提供的服务资源. 2. 定向认证: 客户端会重定向用户请求到 服务器. 3. 用户认证:用户身份认证. 4. 发放票据: 服务器会产生一个随机 ...
随机推荐
- 【TCP/IP】TCP详解笔记
目录 前言 17. TCP 传输控制协议 17.1 引言 17.2 TCP 服务 17.3 TCP的首部 18. TCP连接的建立与终止 18.1 引言 18.2 连接的建立与终止 18.2.1 建立 ...
- 解决java socket在传输汉字时出现截断导致乱码的问题
解决java socket在传输汉字时出现截断导致乱码的问题 当使用socket进行TCP数据传输时,传输的字符串会编码成字节数组,当采用utf8编码时,数字与字母长度为1个字节,而汉字一般为3个字节 ...
- Lin语法(Linq对数据库操作)
一.Linq语句的应用: var queryAllCustomers = from cust in customers group cust by cust.City into custGroup ...
- 安装nodejs版本模块报错notsup Unsupported platform for n
使用npm install -g n报错 如果出现npm ERR! notsup Unsupported platform for n@6.7.0: wanted {"os":&q ...
- 源代码管理相关命令(Git常用命令、Nuget常用命令、CMD常用命令)
Git常用命令 源代码工具 工具名称 相关地址 Git Git for Windows VSC Visual Studio Code VSC插件(Gitlen) GitLens - Git super ...
- 8、ITSM基本概念(2)
6.流程和职能: 7.故障管理: (1)故障管理的输入和输出: (2)故障管理的目标: 优先解决影响度大的事件: (3)故障管理的指标: (4)故障管理的流程: 8.问题管理: (1)问题管理的输入和 ...
- gRPC四种模式、认证和授权实战演示,必赞~~~
前言 上一篇对gRPC进行简单介绍,并通过示例体验了一下开发过程.接下来说说实际开发常用功能,如:gRPC的四种模式.gRPC集成JWT做认证和授权等. 正文 1. gRPC四种模式服务 以下案例演示 ...
- 剑指offer 1-5
二维数组中的查找 题目:在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中 ...
- STM32中的GPIO笔记
1.GPIO是STM32可控制的引脚,STM32的GPIO被分成很多组,每组有16个引脚.每个GPIO端口包含:2个32位配置寄存器(CRL.CRH),2个32位数据寄存器(IDR.ODR),1个32 ...
- 性能基准DevOps之如何提升脚本执行效率
1.宝路说 宝路最近一直在自我思考:性能基准DevOps工作已经开展一段时间了,目前我们确实已经取得了一些成果,显然这还远远不够.趁闲暇之余跟组员进行了简单的头脑风暴!于是这就有了今天的主题,当然这仅 ...