首页 > 其他分享 >关于多线程操作单个变量进行加1问题的分析

关于多线程操作单个变量进行加1问题的分析

时间:2022-08-17 22:35:16浏览次数:54  
标签:200 执行 变量 线程 单个 操作 100 多线程

关于多线程操作单个变量进行加1问题的分析

  摘要:在多线程的学习中,我们经常会接触到一个例子,这个例子也是一个重要的面试题,在此我详细的分析这个问题

  问题:我们现有两个线程,这两个线程公共的对一个变量进行100次++操作,那么我们会得到怎样的结果?

  答案:我们的到的结果不固定,我们会得到一个在2~200之间的随机数。

  疑点:我们为什么会得到这样一个随机数呢?首先这个问题体现出的是多线程对公共资源进行读写操作的时候不加锁的后果,这个我们大多数人都可以理解,不加锁会导致读后写的问题,也就是我们在计算中会相互覆盖,导致我们的计算结果不可信,但是关键在于,我们为什么会得到一个2~200之间的数字,而不是1~200之间的数字呢

  分析:为了更加简洁明快的了解这个问题,我们先附上代码:

package com;

public class Try {
    public static void main(String args[]){
        final int[] a = {0};
        Thread t1 = new Thread(){
            @Override
            public void run(){
                for(int i = 0;i<10000;i++){
                    a[0]++;
                }
            }
        };
        Thread t2 = new Thread(){
            @Override
            public void run(){
                for(int i = 0;i<10000;i++){
                    a[0]++;
                }
            }
        };
        t1.start();
        t2.start();
    }
}

  在此存在两个线程对一个公共资源区进行++操作,各自进行100次,对于每个线程中的操作,我们可以分为三个部分:

1.获取到资源上的值
2.为数值进行加一操作
3.将自己计算得到的数值放回到内存上

  需要注意的是,在多线程中,执行完每一个操作之后,都有可能被切换除去执行另外的一个线程。因此我们不难假设一种最坏情况:A线程在获取到资源之后,进行了一次加1操作,之后便被线程B夺走了使用权,线程B加这些数值加到了99之后,正要进行第100次操作,但是在执行完第99次操作之后,就被线程A夺取了CPU使用权,线程A此时将1写在了内存上,将99覆盖了,之后线程B继续执行,B将获取到线程A刚刚写入的1,并进行了一次加1操作,得到了2,之后被A打断,A执行完自己,并将100写入到了内存中,之后B线程将2写入到内存中,覆盖了100,因此这种情况就是2,而最好情况就是这两个线程阴差阳错的没有发生覆盖的情况,正好加到了200。所以这个问题的结果就是2~200。

  需要注意的是在这个问题中结果是不会出现2以下的情况的,如果想出现结果为1,那么我们就需要保证1覆盖了一个100,这是因为我们需要保证让另外一个线程完全结束,否则这个结果一定还会被++,结果就不是1了,但是我们实际上不可能让一个线程得到为1的结果,因为其中一个线程是一定要执行100次的。我们如果想让结果最小,一定要让两个线程发生相互覆盖,因为需要相互覆盖,我们必须保证其中一个线程执行到最后一次,然后被覆盖,之后让另一个线程执行完,执行完后这个线程继续执行,在为刚才得到的1进行加一操作之后结束,简而言之,两个线程都必须执行,而相互覆盖的结果就是2。

  总而言之,得到2的极端过程就是:线程A执行,加一操作之后得到1,然后被线程B打断,B执行了99次之后被A打断,A执行到将1写入到内存之后又被B打断,B获取到1之后进行加1操作之后被A打断,A执行完毕得到了100,将100写入到了内存中,然后B线程中将自己的2写入到了内存中,2将100覆盖了,得到了2。因此在这个问题中,答案是2~200,记住这个答案。

标签:200,执行,变量,线程,单个,操作,100,多线程
From: https://www.cnblogs.com/B307-NCAI/p/16597015.html

相关文章

  • 多线程-浅析线程安全
    多线程-共享模型之管程本文章是根据黑马JUC课程编写,记录的笔记1共享带来的问题在平常开发中,很多时候都会遇到共享数据的问题,比如售票,库存。那么如何就会引出一个疑......
  • 多线程.线程优先级
    Priority优先级线程优先级用数字表示,范围从1~10Thread.MIN_PRIORITY=1;Thread.MAX_PRIORITY=10;Thread.NORM_PRIORITY=5;使用以下方式改变或获取优先级:g......
  • std::condition_variable 条件变量
    std::condition_variable条件变量 voidwait(std::unique_lock<std::mutex>&lock);#1template<classPredicate>voidwait(std::unique_lock<std::mutex>&lo......
  • [记]Rust在多线程下修改共享变量的值
    1.usestd::time::Duration;usestd::sync::{Arc,Mutex};usestd::thread;fnmain(){letokz="2333".to_string();letapple=Arc::new(Mutex::......
  • SpringBoot 多线程
    关于SpringBoot中多线程的两个注解:@Async是spring为了方便开发人员进行异步调用而出现的。在方法上加入这个注解,spring会从线程池中获取一个新的线程来执行方法,实现异步调......
  • Nodejs 多进程与多线程
    为什么要使用多进程多进程与多线程介绍Nodejs多进程和多线程使用与区别cluster为什么需要多进程nodejs单线程,在处理http请求的时候一个错误都会导致进程退出,这是灾......
  • 记录一个i变量引发的事故
    概述近期开发中遇到一个特别的问题,觉得很有必要与你下来。就是由于在开发中一个很小的疏忽,导致了很大的问题,是什么呢?现象我的程序突然引发了v8内部的错误,提示都是c++的,......
  • Python爬虫之多线程异步爬虫,非常详细
    Python爬虫之多线程爬虫在使用Python的过程中,我们可能遇到这样一个场景,需要下载某一个网站上的多个资源;例如:我们想下载豆瓣电影Top250所有的宣传图片具体代码如下......
  • 03 - 多线程之间如何实现通讯
    Java多线程之间如何实现通讯多个线程之间通过wait,notify通讯publicclassThread007{classRes{publicStringuserName;publiccharuserSex......
  • 奇淫巧技,CompletableFuture 异步多线程是真的优雅
     一个示例回顾Future一些业务场景我们需要使用多线程异步执行任务,加快任务执行速度。JDK5新增了Future接口,用于描述一个异步计算的结果。虽然Future以及相关使用......