单例模式在多线程下的数据修改问题(即线程不安全),spring中是如何保证单例的线程安全问题的
admin
2024-01-21 04:37:48
0

单例模式在多线程下带来的赋值问题

问题描述:现在有一个操作:(在饿汉式下,即使用静态内部类保证单例)

1.获取一次单例的对象并对单例中的属性值进行赋值,

2.此时开启一条线程循环1000次去获取单例中的属性值

3.再次获取一个单例的对象并再次赋值

会产生一个现象当步骤3赋值后步骤2中线程获得的值还可能是步骤1的值

原因:在步骤3进入且准备更改步骤1的值时此时步骤2的线程获取到了步骤1的值且在步骤3赋值完成且输出后线程的值才输出,所以导致了线程在步骤1的值已经修改的情况下还能获取到步骤1的值。

下面看代码:

public class Test03 implements Runnable{public static void main(String[] args) {// 第一次获取单例对象且赋值Singleton03Singleton03 s1 = Singleton03.getInstance();System.out.println(s1.id=1);System.out.println(s1.age=18);System.out.println(s1.name="邹飞鸣");// 开启线程,循环1000次获取单例对象(Singleton03)的属性值Test03 test03 = new Test03();new Thread(test03).start();// 睡眠一下,防止线程还没开辟就将步骤3的代码运行了try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}// 第二次获取单例对象且赋值Singleton03Singleton03 s2 = Singleton03.getInstance();System.out.println(s2.id=2);System.out.println(s2.age=20);System.out.println(s2.name="邹飞");}@Overridepublic void run() {for (int i=0;i<1000;i++) {Singleton03 s3 = Singleton03.getInstance();System.out.println("进入多线程+"+s3);}}
}
class Singleton03{// 方便查看属性值@Overridepublic String toString() {return "Singleton03{" +"id=" + id +", age=" + age +", name='" + name + '\'' +'}';}public int id;public int age;public String name;private Singleton03(){}// 静态内部类private static class HolderClass{private final static Singleton03 s = new Singleton03();}public static Singleton03 getInstance(){return HolderClass.s;}
}

结果:重复输出太多只取重要有变化的一段

1																			 // 这是第一次修改
18
邹飞鸣
进入多线程+Singleton03{id=1, age=18, name='邹飞鸣'}
。。。
进入多线程+Singleton03{id=1, age=18, name='邹飞鸣'}
进入多线程+Singleton03{id=1, age=18, name='邹飞鸣'}
进入多线程+Singleton03{id=2, age=18, name='邹飞鸣'}      // 可以看到从这里开始数据变化
进入多线程+Singleton03{id=2, age=18, name='邹飞鸣'}
2
20
进入多线程+Singleton03{id=2, age=18, name='邹飞鸣'}
邹飞
进入多线程+Singleton03{id=2, age=20, name='邹飞'}			// 变化完成
进入多线程+Singleton03{id=2, age=20, name='邹飞'}
。。。

可以看到步骤3更改了步骤1的age值但是下一个线程输出的age值还是步骤1的。所以在特定条件下是可能存在属性值全是步骤1的值。

注:赋值操作不是连贯的,即不是原子性操作,当我们把三步的赋值操作设置成原子操作后是有很大概率实现上述说的

如何避免:加个锁。

注:那在spring中的单例在多线程下是如何保证线程安全的呢?

结论:

1.spring中的IoC容器是不保证单例在并发下的线程安全问题。

2.可使用synchronize来保证(太消耗性能)

3.使用ThreadLocal来保证多线程下的线程安全问题

详细讲之前先说一下什么是无状态单例和有状态单例:

  • 无状态单例:要设置成单例的类中没有任何存储数据或者修改数据的能力,如:没有成员方法或者成员方法被final修饰,单纯作为一个模板,即使要使用也是外部输入数据进去。就好比我们只在类中定义方法不定义成员变量,这样即使在多线程下存在线程安全问题,但由于没有操作数据的修改或者删除,再怎么不安全也不会影响到正常使用。
  • 有状态单例:成为单例的类中存在成员方法,这样当其他类获取到单例对象时可以修改单例对象中的属性值,而一旦是多线程并发下去修改属性值就会出现线程安全问题

解决方法:

1.使用ThreadLocal:需要自己在spring中设置,当开启一条线程时可获取有状态单例的一个副本存储进ThreadLocal中,ThreadLocal中的数据结构是(K,V)K值存储线程对象,V值存储单例副本。这样每个线程都有专属于自己的副本,就避免了线程安全问题

2.使用synchronize。

3.spring中Bean的作用域有两种:singleton(每次获取同一单例),prototype(每次获取新的单例),我们使用后者即可

注:spring中常见的都是无状态的单例,所以不用在意线程安全问题,只有自己写的业务类时才需要考虑。

吐槽:

妈的,这玩意不是常识吗?大部分并发下的这种操作即使不是单例模式也有可能发生啊。

什么菜*面试官、问个问题都不会问,关键是问出来还支支吾吾自己解释不了让我自己回去查?what?还说是啥缓存机制?

面试官原问题是:在单例模式下,类A获取单例对象且修改对象中的属性值,然后类B也获取对象也修改单例对象属性值,此时类C能否获取到类A修改的属性值?

我当时就在想这是什么**问题,我还反复确认。我还以为是SpringBoot的特有属性,我还问了一句说这是不是SpringBoot特有属性,如果在平常的单例模式下就不会存在这种情况?结果他说不知道还让我回去查,妈的越想越气,不知道你当什么问题出?淦!

相关内容

热门资讯

购物狂电影的最后一幕那个弃婴 ... 购物狂电影的最后一幕那个弃婴 是怎么回事?是主角的小时候吧,讲她为什么是购物狂,因为她小时候被抛弃在...
方法决定成败 方法决定成败没错,方法决定成败,态度决定一切,心态决定效率。送你这几句名言,以资鼓励。
霞秋的意思?想表达晚年幸福? 霞秋的意思?想表达晚年幸福?霞秋的意思?想表达晚年幸福?... 霞秋的意思?想表达晚年幸福? 展...
关于“欣赏”的名言和事例 关于“欣赏”的名言和事例19世纪末,美国西部的密苏里有一个坏孩子,他偷偷地向邻居家的窗户扔石头,还把...
自己发的语音总是不敢去听,怎么... 自己发的语音总是不敢去听,怎么让自己勇敢去听呢?怎么说呢,其实你录下来的声音就是别人听到的,只是因为...
格物致知的真正意义是什么? 格物致知的真正意义是什么?提示:可以从文章内容中直接找到答案。? 参考答案:格物致知的真正...
醒悟中心卢卫斌老师谈强迫症的治... 醒悟中心卢卫斌老师谈强迫症的治疗为什么需要禅修练习  强迫症是一种复合型心理障碍,有其独特的障碍模型...
宣化那有好玩的地方 宣化那有好玩的地方有吗? 「莫等闲,白了少年头。空b切」
水深水浅东西涧 云去云来远近山... 水深水浅东西涧 云去云来远近山是什么意思  涧水或东或西时深时浅,山峦亦近云雾盘桓.  作品原文  ...
我的妹妹不可能那么可爱 讲的是... 我的妹妹不可能那么可爱 讲的是什么?就是有一个长的很可爱明明可以很受欢迎【也确实很受欢迎】的妹纸爱好...
童话诗有什么特点 童话诗有什么特点 童话诗(Fairy tale poem),故事诗的一种,现代诗的一种体裁。是以童话...
一块姜在挡车的是什么歌 一块姜在挡车的是什么歌一块姜在挡车的是什么歌感应:泳儿的歌我听的不多,但这首歌尤其的熟悉是一个人生活...
MP3出问题 MP3出问题我选其他歌,它都会跳回去原来那首歌,有时候还更厉害,显示这首歌的文件名字,唱另外一首歌出...
在金庸的设定里,一个武林高手可... 在金庸的设定里,一个武林高手可以打赢100个人已经是极限,但500个武林高手一定打不过1000名普第...
唐诗人张九龄"海上生明月天涯天... 唐诗人张九龄"海上生明月天涯天涯共此时"一诗全文?望月汪渗怀远 唐· 张九龄海上生明月,天涯共此时。...
暗里着迷歌曲深意? 暗里着迷歌曲深意?歌曲《暗里着迷》是刘德华在1993年发行的一首歌,他一直称这一首歌是自己半生中最重...
好听的名字 好听的名字 好听的名字有:圣杰,俊楠,皓轩,雨泽,智宸,明杰,峻熙,泽林,沛荣,嘉浩。1、圣杰:“圣...
伊索语言关于谣言的故事 伊索语言关于谣言的故事《伊索寓言》是世界上流传最早的最广的寓言故事集之一,《伊索寓言》相传为公元前六...
《庄子》记佝偻承蜩的故事和解释 《庄子》记佝偻承蜩的故事和解释原文 仲尼适楚,出于林中,见佝偻者承蜩,犹掇之也。仲尼曰:“子巧乎!有...
幼儿园托班教室墙面布置幼儿园托... 幼儿园托班教室墙面布置幼儿园托班教室的布置幼儿园教室是许多孩子家长关注的重点之一。然后,幼儿园教室的...