当前位置: 首页 > news >正文

论文引用网站怎样做脚注佛山网页网站设计

论文引用网站怎样做脚注,佛山网页网站设计,大数据智能营销获客系统,互联网电商网站建设竞态 对于同样的输入,程序的输出有时候正确而有时候却是错误的。这种一个计算结果的正确性与时间有关的现象就被称为竞态(RaceCondition) 导致竞态的常见原因是多个线程在没有采取任何措施的情况下并发更新、读取同一个共享变量。 竞态往往伴…

竞态

对于同样的输入,程序的输出有时候正确而有时候却是错误的。这种一个计算结果的正确性与时间有关的现象就被称为竞态(RaceCondition)

导致竞态的常见原因是多个线程在没有采取任何措施的情况下并发更新、读取同一个共享变量。

竞态往往伴随着数据的脏读问题,即线程读取到一个过时的数据;丢失更新问题,即一个线程丢失数据所做的更新没有体现在后续其他线程对该数据的读取上。

竞态实例:

模拟RequestID生成器,RequestID是一个固定长度的编码字符串,其中最后三位是在0~999循环递增的序列号。

public final class RequestIDGenerator implements CircularSeqGenerator {/*** 保存该类的唯一实例*/private final static RequestIDGenerator INSTANCE = new RequestIDGenerator();private final static short SEQ_UPPER_LIMIT = 999;private short sequence = -1;// 私有构造器private RequestIDGenerator() {// 什么也不做}/*** 生成循环递增序列号** @return*/@Overridepublic short nextSequence() {if (sequence >= SEQ_UPPER_LIMIT) {sequence = 0;} else {sequence++;}return sequence;}/*** 生成一个新的Request ID** @return*/public String nextID() {SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");String timestamp = sdf.format(new Date());DecimalFormat df = new DecimalFormat("000");// 生成请求序列号short sequenceNo = nextSequence();return "0049" + timestamp + df.format(sequenceNo);}/*** 返回该类的唯一实例** @return*/public static RequestIDGenerator getInstance() {return INSTANCE;}
}

竞态demo:

public class RaceConditionDemo {public static void main(String[] args) throws Exception {// 客户端线程数
//    args = new String[] {"4"};//Runtime.getRuntime().availableProcessors()-- 返回可用处理器的Java虚拟机的数量int numberOfThreads = args.length > 0 ? Short.valueOf(args[0]) : Runtime.getRuntime().availableProcessors();Thread[] workerThreads = new Thread[numberOfThreads];for (int i = 0; i < numberOfThreads; i++) {workerThreads[i] = new WorkerThread(i, 10);}// 待所有线程创建完毕后,再一次性将其启动,以便这些线程能够尽可能地在同一时间内运行for (Thread ct : workerThreads) {ct.start();}}// 模拟业务线程static class WorkerThread extends Thread {private final int requestCount;public WorkerThread(int id, int requestCount) {super("worker-" + id);this.requestCount = requestCount;}@Overridepublic void run() {int i = requestCount;String requestID;RequestIDGenerator requestIDGen = RequestIDGenerator.getInstance();while (i-- > 0) {// 生成Request IDrequestID = requestIDGen.nextID();processRequest(requestID);}}// 模拟请求处理private void processRequest(String requestID) {// 模拟请求处理耗时Tools.randomPause(50);System.out.printf("%s got requestID: %s %n",Thread.currentThread().getName(), requestID);}}
}

当args = new String[] {"4"}; 时,理论上序列号最后三位是:000-039,但是多次运行结果有时正确有时返回000-038,有时000-037。

截取部分运行结果,其中work-0和work-2线程返回的值是一样的。该程序在运行过程中出现了竞态。

worker-0 got requestID: 0049190620170236002 
worker-3 got requestID: 0049190620170236000 
worker-0 got requestID: 0049190620170236004 
worker-1 got requestID: 0049190620170236003 
worker-2 got requestID: 0049190620170236002 

nextSequence()中的 sequence++ 实际上相当于如下伪代码:

load(sequence,r1); //指令①:从内存将sequence的值读取到寄存器r1(读取共享变量)
increment(r1);     //指令②:将寄存器的r1值增加1(共享变量做计算)
store(sequence,r1); //指令③:将寄存器r1的内容写入sequence对应的内存空间(更新变量)

发生原因:

一个线程在执行完指令①之后到开始执行指令②的这段时间内其他线程可能已经更新了共享变量的值,这就使得该线程在执行指令②的时候使用的是共享变量的旧值,即脏读数据。接着,该线程把根据这个旧值算出来的结果更新到共享变量,而这又使得其他线程对该变量所做的更新被覆盖,造成更新丢失。

竞态: 一个线程读取共享变量并以该共享变量为基础进行计算的期间另外的一个线程更新了该共享变量的值而导致的干扰(读取脏数据)或冲突(丢失更新)的结果。

竞态防止

共享变量修改为局部变量

public class NoRaceCondition {public int nextSequence(int sequence) {// 以下语句使用的是局部变量而非状态变量,并不会产生竞态if (sequence >= 999) {sequence = 0;} else {sequence++;}return sequence;}}

由于不同线程各自访问各自的那一部分局部变量,所以局部变量不会导致竞态。、

添加synchronized关键字

public class SafeCircularSeqGenerator implements CircularSeqGenerator {private short sequence = -1;@Overridepublic synchronized short nextSequence() {if (sequence >= 999) {sequence = 0;} else {sequence++;}return sequence;}
}

限制只能被一个线程执行

线程安全和非线程安全

线程安全 如果一个类在单线程环境下运行正常,并且在多线程环境下,不做任何改变的情况下也能正常运行,那我们就称其是线程安全的,相应的我们称这个类具有线程安全性。

非线程安全 反之我们则为非线程安全。

线程安全概述:

原子性

原子的意思是不可再分。对于设计共享变量访问的操作,若该操作从其执行线程以外的任意线程来看是不可分割的,那么该操作就是原子操作,相应的我们称该操作具有原子性
原子操作是多线程环境下的一个概念,他是针对访问共享变量的操作而言的。原子操作的不可分割包括以下两层含义:

  • 访问(读写)某个共享变量的操作从其执行线程以外的任何线程来看,
    该操作要么已经执行结束要么尚未发生,即其他线程不会‘看到’该操作执行了部分的中间效果。
  • 访问一组共享变量的原子操作是不能够被交错的。

java如何实现原子性:

  • 使用锁(lock)。锁具有排他性,它能保证一个共享变量在任意一个时刻只能够被一个线程访问。
  • 另一种是利用处理器提供的专门CAS指令。CAS指令实现原子性的方式和锁实现原子性的方式实质上是相同的,差别在于锁是在软件层次实现,而CAS是直接在硬件(处理器和内存)层次实现,可以看做“硬件锁”。
可见性

可见性:在多线程环境下,一个线程对共享变量做了更新,而其它线程在后续的访问过程中无法立刻读取到更新后的内容,甚至永远无法读取到更新后的内容。
后续访问该变量的线程可以读取到更新后的结果,我们称这线程对共享变量的更新对其他线程可见。反之,则称为不可见。
不可见产生的原因:

  • 代码没有给编译器足够的提示,使其认为该状态变量只有一个线程访问,从而使编译器为了避免重复读取该变量而对代码做了优化。
  • 可见性问题与与计算机的储存系统也有关。

如何保证可见性?
对实例变量添加关键字:volatile

  • 一个作用是提示JIT编译器被修饰的变量可能被多个线程共享,以阻止编译器做出可能导致程序不正常的优化。
  • 另一个作用是读取一个volatile关键字修饰的变量会使相应的处理器执行刷新处理器缓存的动作,写一个volatile修饰的变量会使相应的处理器执行冲刷处理器缓存的动作,从而保障了可见性。

转载于:https://www.cnblogs.com/sanzashu/p/11065294.html

http://www.yayakq.cn/news/826864/

相关文章:

  • org后缀的网站wordpress前台发文章
  • 深圳网站建设黄浦网络 骗子wordpress手机后台
  • 企业网站首页html模板海南省住房公积金管理局电话号码
  • 长沙百度网站推广优化去哪里学习建设网站
  • 自动优化网站建设咨询公司做网站 要准备哪些素材
  • 企业集团网站源码如何做自己的在线作品网站
  • 企业网站建设对网络营销的影响代理注册企业登记
  • 网站正在建设中php深圳营销型网站建设推广服务
  • 个人网站用凡科建站好吗厦门知名做企业网站设计的公司
  • 行业外贸网站建设东莞网站建设企慕
  • 杭州定制网站wordpress好插件
  • 中国建设监理协会网站怎样用c语言做网站
  • 做智能网站平台青浦网站制作公司
  • 做网站发表的赚钱企业网站建设步骤
  • 怎样免费注册自己网站的域名为何要屏蔽网站快照
  • 电商 网站 设计自适应h5网站模板
  • 建设外贸网站费用wordpress后台系统
  • 网站建设主题与建设目标织梦响应式网站
  • 在什么网站上可以做中学数学家教中小型门户网站
  • 搜狐员工做网站的工资多少钱机械建设网站制作
  • 深圳 购物商城网站建设济南房管局官网
  • 深圳网站建设信科便宜建一个公司网站要多少钱
  • 做网站ftp深圳网站制作建设服务公司
  • 苏州最大的网站建设公司网线水晶头的接线方法
  • 做网站的收获应用软件有哪些
  • 图片生成链接网站knowall wordpress
  • 城市管理如何宣传市建设网站东莞网站模板
  • 单位网站建设和维护上海人才招聘网官网
  • 学做网站需要什么基础临沂网站哪家好
  • 陕西专业网站开发公司网站备案怎么做