【思考】Java中多个线程操作同一个实例中的同一个方法会有什么影响?

本人是刚入门的小白,最近在重新学习spring;在理解spring中默认单例bean时引起了我对于标题的思考。

于是上网搜索,众多的回答给了我一点启发,但是都没有醍醐灌顶的感觉,当我尝试从硬件角度思考时似乎答案变得清晰了起来...

在spring中,无论是配置xml还是添加注解  对象的创建默认都是单例的,我们暂且不谈单例的好处是什么,单单来分析一下 如果多个线程同时调用这个实例的同一个方法会发生什么:

 这个有两种情况:

 1、方法只进行简单的数据处理,涉及的变量都是局部变量;

 2、方法会操作全局的变量或者是数据库中的数据;

先来分析一下第一种情况:



// 该方法只对输入的数据进行简单的处理(方法为spring托管的单例对象的方法)

public String sout(String str){

    return str+"字符串进行了变更";

}


/**
 * 假设现在有两个线程同时调用 单例对象(或者同一个实例)的sout方法
 *
 */

// 线程1
singleton.sout("张三");

// 线程2
singleton.sout("李四");

现在思考的地方来了,这个单例对象被创建在堆内存中,现在两个线程同时调用他的sout方法会不会导致一个对象需要处理两个线程的请求造成结果混乱呢?这也是我最初的疑惑,最初类比的是一个机器如果同时给两个人的两个苹果削皮  完成后会不会分不清哪个苹果属于哪个人?

其实这个类比就是错误的,计算机中处理的只是数据,堆内存中的对象其实就是等待被cpu处理的数据块;单个sout方法就是缺少输入的数据块,当方法被调用时cpu读取sout和输入数据整合为完整的数据块进入cpu执行;如果两个线程是被两个cpu处理 那么两个cpu就会分别整合出两个完整的数据块进入cpu执行;

到此问题就清晰了,存于堆内存中的对象只是一种数据形式(并不是之前类比的处理数据的机器)对于cpu来说只是一条可处理的数据而已,无论是单个对象还是多个对象cpu只将其读取进来和输入数据进行整合(cpu读取对象不会影响到对象,这个对象任然可以被其他cpu读取)然后处理;对象和输入数据都只是数据,cpu才是机器;创建的对象只是一种常驻内存的能够处理数据的数据逻辑(也还是数据)

========================================================

所以说对于第一种情况并不会有什么影响,但是对于第二张情况影响就比较大了

// 假设下面的方法是对内存中 A 的大小进行修改(全局变量可被所有线程访问)

public void updateNum(){

       A -= 10;

}



/**
 * 现在有两个线程同时都调用了这个方法,会有什么情况发生
 */


// 线程1
thread1.updateNum();

// 线程2
thread2.updateNum();

现在两个线程同时调用这个方法;下面简单分析一下:

线程1调用方法,cpu1读取到A的值为100  此时进行处理  A的值修改为90

于此同时线程2也调用方法,cpu2同时读取A的值也是100  cpu2进行处理  A的值修改为90

现在两个线程都处理完之后 A的值为90;可见这种多线程同时修改全局变量会出现问题。

多线程操作共享数据涉及到同步和锁的问题在此不过多赘述,本文旨在讨论多线程操作单例bean时有什么影响,分析完可见操作线程自身的局部变量时并不会产生什么影响;对象只是存在于内存中的赋予处理数据逻辑的数据,cpu才是真正处理数据的机器;相同的对象无论一个还是两个都是提供给cpu读取的不存在两个线程竞争对象的问题。

ps:以上内容仅仅是一个刚入门小白的思考和自身理解,如有不对的地方 感谢指正!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值