共享虚拟主机普惠版做网站无代码软件开发
- 作者: 五速梦信息网
- 时间: 2026年04月20日 11:09
当前位置: 首页 > news >正文
共享虚拟主机普惠版做网站,无代码软件开发,seo教程免费分享,塘下建设银行网站竞态 对于同样的输入#xff0c;程序的输出有时候正确而有时候却是错误的。这种一个计算结果的正确性与时间有关的现象就被称为竞态#xff08;RaceCondition#xff09; 导致竞态的常见原因是多个线程在没有采取任何措施的情况下并发更新、读取同一个共享变量。 竞态往往伴… 竞态 对于同样的输入程序的输出有时候正确而有时候却是错误的。这种一个计算结果的正确性与时间有关的现象就被称为竞态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
- 上一篇: 共享ip做网站杭州洛可可设计公司
- 下一篇: 构建企业门户网站的方法音乐播放网站开发pc端
相关文章
-
共享ip做网站杭州洛可可设计公司
共享ip做网站杭州洛可可设计公司
- 技术栈
- 2026年04月20日
-
共享ip网站 排名影响带商城的企业网站源码
共享ip网站 排名影响带商城的企业网站源码
- 技术栈
- 2026年04月20日
-
共同建设网站协议平台搭建需要什么技术
共同建设网站协议平台搭建需要什么技术
- 技术栈
- 2026年04月20日
-
构建企业门户网站的方法音乐播放网站开发pc端
构建企业门户网站的方法音乐播放网站开发pc端
- 技术栈
- 2026年04月20日
-
构建网站的步骤重庆档案馆建设网站
构建网站的步骤重庆档案馆建设网站
- 技术栈
- 2026年04月20日
-
构建一个网站需要什么html做网站例子
构建一个网站需要什么html做网站例子
- 技术栈
- 2026年04月20日
