• 原子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 原理 应用的更多相关文章

  1. 采用CAS原理构建单点登录

    企业的信息化过程是一个循序渐进的过程,在企业各个业务网站逐步建设的过程中,根据各种业务信息水平的需要构建了相应的应用系统,由于这些应用系统一般是在不同的时期开发完成的,各应用系统由于功能侧重.设计方法 ...

  2. JAVA CAS原理深度分析-转载

    参考文档: http://www.blogjava.net/xylz/archive/2010/07/04/325206.html http://blog.hesey.net/2011/09/reso ...

  3. JAVA CAS原理

    转自: http://blog.csdn.net/hsuxu/article/details/9467651 CAS CAS: Compare and Swap java.util.concurren ...

  4. 【转】JAVA CAS原理深度分析

    java.util.concurrent包完全建立在CAS之上的,没有CAS就不会有此包.可见CAS的重要性. CAS CAS:Compare and Swap, 翻译成比较并交换. java.uti ...

  5. JAVA CAS原理深度分析

    参考文档: http://www.blogjava.net/xylz/archive/2010/07/04/325206.html http://blog.hesey.net/2011/09/reso ...

  6. CAS原理与协议

    SSO英文全称Single Sign On,单点登录. SSO是在多个应用系统中,用户仅仅须要登录一次就能够訪问全部相互信任的应用系统. SSO的解决方式非常多,比方收费的有UTrust.惠普灵动等, ...

  7. JAVA CAS原理深度分析(转)

    看了一堆文章,终于把JAVA CAS的原理深入分析清楚了. 感谢GOOGLE强大的搜索,借此挖苦下百度,依靠百度什么都学习不到! 参考文档: http://www.blogjava.net/xylz/ ...

  8. Java中的CAS原理

    前言:在对AQS框架进行分析的过程中发现了很多CAS操作,因此有必要对CAS进行一个梳理,也便更清楚的了解其原理. 1.CAS是什么 CAS,是compare and swap的缩写,中文含义:比较交 ...

  9. JAVA CAS原理浅谈

    java.util.concurrent包完全建立在CAS之上的,没有CAS就不会有此包.可见CAS的重要性. CAS CAS:Compare and Swap, 翻译成比较并交换. java.uti ...

  10. CAS 原理

    基础模式 1. 访问服务:  客户端发送请求访问应用系统提供的服务资源. 2. 定向认证:  客户端会重定向用户请求到 服务器. 3. 用户认证:用户身份认证. 4. 发放票据: 服务器会产生一个随机 ...

随机推荐

  1. mybatis自定义打印执行时间并格式化sql插件

    打印SQL的执行时间,我们可以实现mybatis官方我们提供的接口org.apache.ibatis.plugin.Interceptor,我们可以拦截的类有多个Executor,StatementH ...

  2. 【模板】Tarjian求LCA

    概念 公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点 举个例子吧,如下图所示4和5的最近公共祖先是2,5和3的最近公共祖先是1,2和1的最近公共祖先是1. 算法 常用的求LCA的算法有:Ta ...

  3. bzoj2839 集合计数(容斥+组合)

    集合计数 内存限制:128 MiB 时间限制:1000 ms 标准输入输出     题目描述 一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得 ...

  4. windows+R键的应用

    windows+R:然后输入以下几个命令 1.cmd :用于Windows命令行操作,比如:ping某个网络,看看是不是通的,或者directory等等Windows命令行操作 2.远程桌面连接:ms ...

  5. vue环境搭建以及使用vue-cli创建项目

    我要跑vue项目,所以我要搞vue. 1.环境搭建 进入node官网下载对应版本的node,一步步安装即可. 安装会自动配置路径和npm包管理环境,通过node -v进行验证 2.安装vue-cli脚 ...

  6. 三代码使用QScrollArea

    QScrollArea是QT封装好的一个滑动界面类 构造函数如下: 指定一个父对象就行,构造函数提供一个滑动的区域,但是这个区域里是没有内容的,构造函数介绍里面让我们看setWidget()这个函数, ...

  7. 14、redis安装及数据类型

    14.0.服务器配置: 服务器名称 ip地址 controller-node1 172.16.1.90 14.1.什么是redis: 1.redis的特点: (1)redis是一个开源的使用c语言编写 ...

  8. 『无为则无心』Python序列 — 23、Python序列的公共API

    目录 1.运算符 @1.+加号 @2.*乘号 @3.in或not in 2.公共方法 @1.len()方法 @2.del和del() @3.max()方法 @4.min()方法 @5.range() ...

  9. c++11 线程间同步---利用std::condition_variable实现

    1.前言 很多时候,我们在写程序的时候,多多少少会遇到下面种需求 一个产品的大致部分流程,由工厂生产,然后放入仓库,最后由销售员提单卖出去这样. 在实际中,仓库的容量的有限的,也就是说,工厂不能一直生 ...

  10. 37.qt quick- 高仿微信实现局域网聊天V3版本(添加登录界面、UDP校验登录、皮肤更换、3D旋转)

    1.版本介绍(已上传至群里) 版本说明: 添加登录界面. UDP校验登录. 皮肤更换. 3D旋转(主界面和登录界面之间切换) . 效果图如下所示: 如果效果图加载失败,可以去哔哩哔哩 https:// ...