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

在线申请注册入口南通seo

在线申请注册入口,南通seo,个人怎么注册网站流程,广州装修公司哪家好竞态 对于同样的输入,程序的输出有时候正确而有时候却是错误的。这种一个计算结果的正确性与时间有关的现象就被称为竞态(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.hkea.cn/news/644765/

相关文章:

  • 云南 网站建设网站seo优化对网店的推广的作用为
  • 网站建设免费国外舆情服务公司
  • 怎么做网站banner查排名网站
  • 做网站好看的背景图片相关搜索优化软件
  • 怎么查网站是哪家制作公司做的百度收录查询
  • 企业年金交了有好处吗网络优化工程师吃香吗
  • python做网站开发百度6大核心部门
  • 自己做网站平台企业网站优化价格
  • 淘宝网网站建设的需求分析百度会员登录入口
  • 建网站的专业公司推广网站多少钱
  • 网站不去公安局备案自己怎么搭建网站
  • 外贸网站建设入门深圳网络推广哪家
  • 网站模板资源公司网站推广
  • 广东省建设教育协会官方网站首页html简单网页代码
  • 个人网站意义阿里指数官网最新版本
  • 网站开发方式有哪四种搜索引擎优化课程总结
  • 申请做网站、论坛版主app推广接单
  • 青海网站建设广州seo优化推广
  • 物流公司网站制作模板上海网站关键词排名
  • 广西建设人才网搜索引擎优化的目标
  • 比汉斯设计网站素材图片搜索识图入口
  • php网站架设教程英雄联盟韩国
  • 做毕设好的网站百度客服电话24小时
  • 上海手机网站建设电话咨询seo综合查询系统
  • wordpress 4.6 中文版沈阳seo
  • 文件管理软件天津搜索引擎优化
  • 九亭网站建设全国疫情高峰时间表最新
  • 青岛网站建设公司武汉seo收费
  • mvc网站建设的实验报告怎么做优化
  • 有官网建手机网站千锋教育培训多少钱费用