-
HashMap 线程安全问题
2019-03-21 21:55:33我们紧接着上节ArrayList 线程安全问题讲下HashMap的线程安全问题. 之前看书,书中经常会提及.HashTable是线程安全的,HashMap是线程非安全的.在多线程的情况下, HashMap会出现死循环的情况.此外,还会推荐使用新的JUC...前言
我们紧接着上节ArrayList 线程安全问题讲下
HashMap的线程安全问题
.之前看书,书中经常会提及.
HashTable是线程安全的,HashMap是线程非安全的.在多线程的情况下, HashMap会出现死循环的情况.
此外,还会推荐使用新的JUC类 ConcurrentHashMap
.今天,我们就将这些幺蛾子一网打尽. 本章, 将主要描述"为什么
HashMap
是非线程安全的? HashMap在多线程的情况下为什么会出现死循环?"
正文 - 准备工作
在讲解
HashMap类的非线程安全问题
之前, 我们需要对于HashMap
的数据结构要有所了解.通过
Eclipse的outline视图
,我们瞄一瞄HashMap的源码内的对象.
通过观察,我们可以发现.HashMap
主要是维护了一个Enrty类型的数组
来存储变量.
即transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
,其中transient
是用于表示不需要序列化的标示,我们不用管他.static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; Entry<K,V> next; int hash; }
我们在看下
Entry类
的源码.通过上述的Entry
源码,我们可以发现它主要包括几个部分:key/value/hash/next
.
在JDK1.7
中的HashMap结构大致如下:
其中的每一块值,是一个Entry类型的链表.(在JDK1.8 之后,当Entry链表
的长度多于一定的值的时候,会将其转换为红黑树. PS: 为了在O(log2N)的时间内获取到结点的值. 在JDK1.8内的红黑树也是使用链表进行实现的,不必过于在意.)
单线程
resize
操作首先, 与
ArrayList类
一样, 我们先瞄一瞄HashMap的put方法.public V put(K key, V value) { if (table == EMPTY_TABLE) { // 如果table为空的table,我们需要对其进行初始化操作. inflateTable(threshold); } if (key == null) // 如果key为null的话 我们对其进行特殊操作(其实是放在table[0]) return putForNullKey(value); // 计算hash值 int hash = hash(key); // 根据hash值获取其在table数组内的位置. int i = indexFor(hash, table.length); // 遍历循环链表(结构图类似上图) for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; // 如果找到其值的话,将原来的值进行覆盖(满足Map数据类型的特性.) if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } // 如果都没有找到相同都key的值, 那么这个值是一个新值.(直接进行插入操作.) modCount++; addEntry(hash, key, value, i); return null; }
跟随其后,我们深入
addEntry(hash, key, value, i);
方法一探究竟吧.void addEntry(int hash, K key, V value, int bucketIndex) { if ((size >= threshold) && (null != table[bucketIndex])) { // 如果其大小超过threshold 并且table[index]的位置不为空 // 扩充HashMap的数据结果为原来的两倍 resize(2 * table.length); hash = (null != key) ? hash(key) : 0; bucketIndex = indexFor(hash, table.length); } createEntry(hash, key, value, bucketIndex); }
PS:
mountCount
/size
/threshold
的联系与区别?紧随其后,进入人们经常说的
resize()
方法.void resize(int newCapacity) { Entry[] oldTable = table; int oldCapacity = oldTable.length; if (oldCapacity == MAXIMUM_CAPACITY) { //capacity 容量 threshold = Integer.MAX_VALUE; return; } // 创建一个新的对象 Entry[] newTable = new Entry[newCapacity]; // 将旧的对象内的值赋值到新的对象中 transfer(newTable, initHashSeedAsNeeded(newCapacity)); table = newTable; // 重新赋值新的临界点 threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1); } void transfer(Entry[] newTable, boolean rehash) { // 新table的长度 int newCapacity = newTable.length; for (Entry<K,V> e : table) { while(null != e) { Entry<K,V> next = e.next; if (rehash) { e.hash = null == e.key ? 0 : hash(e.key); } int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } } }
这么一看,主要的
resize()方法
的转换操作都在transfer()方法内
.我们详细的画图了解下这个循环.for (Entry<K,V> e : table) {}
外层循环,循环遍历旧table
的每一个值.这不难理解,因为要将旧table
内的值拷贝进新table
.- 链表拷贝操作.主要是四行代码.
e.next = newTable[i]; newTable[i] = e; e = next;
这个操作一下子比较难懂,我们画图了解一下.
这个图还是有点抽象 我们再将细节进行细分.
1next = e.next
,目的是记录下原始的e.next
的地址.图上为Entry-1-1
.
2e.next = newTable[i]
,也就是将newTable[3]
替代了原来的entry1-1
.目的是为了记录原来的newTable[3]
的链表头.
3newTable[i] = e
,也就死将entry1-0
替换成新的链表头.
4.e = next;
,循环遍历指针.将e = entry1-1
.开始处理entry1-1
.
将步骤细分后,我们可以得到如下:
由上述的插入过程,我们可以看出.这是一个倒叙的链表插入过程.
(比如 1-0 -> 1-1 ->1-2 插入后将变为 1-2 -> 1-1 -> 1-0)
多线程操作 - 分析线程安全?线程非安全?
因为
倒叙链表插入
的情况,导致HashMap
在resize()
的情况下,导致链表出现环的出现.一旦出现了环那么在while(null != p.next){}
的循环的时候.就会出现死循环导致线程阻塞.那么,多线程的时候,为什么会出现环状呢?让我们看下面的例子:首先有2个线程,由上一节我们知道,在
resize()
的过程中,一共有如下四个步骤:Entry<K,V> next = e.next;
e.next = newTable[i];
newTable[i] = e;
e = next;
我们有两个线程,线程A与线程B.线程A在执行
Entry<K,V> next = e.next;
之后,也就是第一个步骤之后,线程阻塞停止了.线程B之间进行了重排序的操作.此时的HashMap内部情况如下所示:- 初始(A阻塞 B运行完毕)
- A唤醒 e=key(3)
A的执行步骤如下:- 线程阻塞前记录 next = key(7)
- 线程唤醒后执行 newTable[3]=null; key(3).next=null;
- newTable[3]=key(3);
- e=next; 即 e = key(7);
- A唤醒 e=key(7)
- next = key(3)
- newTable[3]=key(3); key(7).next=key(3);
- newTable[3]=key(7);
- e=next; 即 e = key(3);
- A唤醒 e=key(3)
- next = key(3).next; 即 next = null;
- newTable[3]=key(7); key(3).next=key(7);
- newTable[3]=key(3);
- e=next; 即 e = null; 循环结束.但是此时已经形成了环路.
Tips
链表出现环?
快,慢指针方法.判断链表中是否有环 ----- 有关单链表中环的问题size、capacity、threshold与loadFactor?
- size为hashMap内的链表结点数目.即
Entry对象的个数
(包括链表内). - capacity为桶的数目.(即Enrty<k,v> []table的长度)
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
- loadFactor 过载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
- threshold 边界值.高于边界值,则HashMap进行
resize
操作.The next size value at which to resize (capacity * load factor).
定义int threshold;
Reference
[1]. HashMap 在 JDK 1.8 后新增的红黑树结构
[2]. (1)美团面试题:Hashmap的结构,1.7和1.8有哪些区别,史上最深入的分析
[3]. Java7/8 中的 HashMap 和 ConcurrentHashMap 全解析
[4]. HashMap?面试?我是谁?我在哪
[5]. JDK7与JDK8中HashMap的实现
[6]. 谈谈HashMap线程不安全的体现
[7]. ConcurrentHashMap源码分析(JDK1.7和JDK1.8)
[8]. HashMap中capacity、loadFactor、threshold、size等概念的解释 -
【Android】BroadcastReceiver安全问题
2019-12-17 21:51:55BroadcastReceiver安全问题 BroadcastReceiver设计的初衷是从全局考虑可以方便应用程序和系统、应用程序之间、应用程序内的通信,所以对单个应用程序而言BroadcastReceiver是存在安全性问题的(恶意程序脚本不断的去...BroadcastReceiver安全问题
BroadcastReceiver
设计的初衷是从全局考虑可以方便应用程序和系统、应用程序之间、应用程序内的通信,所以对单个应用程序而言BroadcastReceiver
是存在安全性问题的(恶意程序脚本不断的去发送你所接收的广播)- 保证发送的广播要发送给指定的对象
当应用程序发送某个广播时系统会将发送的Intent
与系统中所有注册的BroadcastReceiver
的IntentFilter
进行匹配,若匹配成功则执行相应的onReceive
函数。可以通过类似sendBroadcast(Intent, String)
的接口在发送广播时指定接收者必须具备的permission
或通过Intent.setPackage
设置广播仅对某个程序有效。 - 保证我接收到的广播室指定对象发送过来的
当应用程序注册了某个广播时,即便设置了IntentFilter
还是会接收到来自其他应用程序的广播进行匹配判断。对于动态注册的广播可以通过类似registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)
的接口指定发送者必须具备的permission
,对于静态注册的广播可以通过android:exported="false"
属性表示接收者对外部应用程序不可用,即不接受来自外部的广播。
android.support.v4.content.LocalBroadcastManager
工具类,可以实现在自己的进程内进行局部广播发送与注册,使用它比直接通过sendBroadcast(Intent)发送系统全局广播有以下几个好处:- 因广播数据在本应用范围内传播,你不用担心隐私数据泄露的问题。
- 不用担心别的应用伪造广播,造成安全隐患。
- 相比在系统内发送全局广播,它更高效。
LocalBroadcastManager mLocalBroadcastManager; BroadcastReceiver mReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); IntentFilter filter = new IntentFilter(); filter.addAction("test"); mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("test")) { //Do Something } } }; mLocalBroadcastManager = LocalBroadcastManager.getInstance(this); mLocalBroadcastManager.registerReceiver(mReceiver, filter); } @Override protected void onDestroy() { mLocalBroadcastManager.unregisterReceiver(mReceiver); super.onDestroy(); }
- 保证发送的广播要发送给指定的对象
-
实例变量共享造成的非线程安全问题
2020-09-12 23:46:35} } # 输出: Thread is A, count is 3 Thread is E, count is 0 Thread is D, count is 1 Thread is B, count is 3 Thread is C, count is 2 A线程和B线程获取到的count都是3,出现了非现场安全问题。 对count的值...不共享实例变量
测试代码
public class MyThreadNotShared extends Thread { private int count = 5; public MyThreadNotShared(String name){ super(); this.setName(name); } @Override public void run() { super.run(); while (count > 0) { count--; System.out.println("Thread is " + this.currentThread().getName() + ", count is " + count); } } } public class TestInstanceNotShared { public static void main(String[] args) { Thread a = new MyThreadNotShared("A"); Thread b = new MyThreadNotShared("B"); Thread c = new MyThreadNotShared("C"); a.start(); b.start(); c.start(); } } # 输出: Thread is A, count is 4 Thread is C, count is 4 Thread is B, count is 4 Thread is C, count is 3 Thread is A, count is 3 Thread is A, count is 2 Thread is C, count is 2 Thread is B, count is 3 Thread is C, count is 1 Thread is C, count is 0 Thread is A, count is 1 Thread is A, count is 0 Thread is B, count is 2 Thread is B, count is 1 Thread is B, count is 0
程序创建了3个线程,每个线程都有各自的count变量,不存在多个线程访问同一个实例变量问题。
共享实例变量
测试代码
public class MyThreadShared extends Thread { private int count = 5; @Override public void run() { super.run(); count--; System.out.println("Thread is " + this.currentThread().getName() + ", count is " + count); } } public class TestInstanceShared { public static void main(String[] args) { MyThreadShared myThread = new MyThreadShared(); Thread a = new Thread(myThread,"A"); Thread b = new Thread(myThread,"B"); Thread c = new Thread(myThread,"C"); Thread d = new Thread(myThread,"D"); Thread e = new Thread(myThread,"E"); a.start(); b.start(); c.start(); d.start(); e.start(); } } # 输出: Thread is A, count is 3 Thread is E, count is 0 Thread is D, count is 1 Thread is B, count is 3 Thread is C, count is 2
A线程和B线程获取到的count都是3,出现了非现场安全问题。
对count的值处理分为3步(执行这些步骤的过程中会被其他线程所打断):
1、获取count的值;
2、计算count-1;
3、计算结果对count赋值。
A线程和B线程得出相同值的过程如下:
线程/时间 1 2 3 4 5 6 7 A 5 4 4 B 5 4 4 1、在时间单位为1处,A线程取得count变量的值为5。
2、在时间单位为2处,B线程取得count变量的值为5。
3、在时间单位为3处,A线程执行count–计算,将计算后的值4存储到临时变量中。
4、在时间单位为4处,B线程执行count–计算,将计算后的值4也存储到临时变量中。
5、在时间单位为5处,A线程将临时变量中的值4赋值给count。
6、在时间单位为6处,B线程将临时变量中的值4也赋值给count。
7、最终结果就是A线程和B线程得到相同的计算结果4,非线程安全问题出现了。
解决方案
增加synchronized关键字
-
常见App安全问题
2018-06-02 10:32:07常见的 App 安全问题据2015年第三季度移动安全报告显示,Android 16个行业 TOP 10 应用漏洞类别和数量中,Webview远程代码执行占到了第一位,第二位是Webview文明存储密码。这些领域涵盖大家平时工作领域,我们所...常见的 App 安全问题
据2015年第三季度移动安全报告显示,Android 16个行业 TOP 10 应用漏洞类别和数量中,Webview远程代码执行占到了第一位,第二位是Webview文明存储密码。这些领域涵盖大家平时工作领域,我们所面临的漏洞是非常严峻的。
常见安全问题分析
上图可看出Android研发要点约450个,包含组建安全、配置安全、策略安全、通信安全、权限欧洲、DOS安全、ROOT安全等等,今天从这里面挑一些重点讲一下。
组件安全问题。安全有四大原生的组建:
一、Activity,首先是访问权限控制,组建处理不好会导致你的应用被恶意程序进行恶意的页面调用。作为研发人员,我们可以从以下三点来预防和避免这个问题:
私有的Activity不应该被其他应用启动且应该确保相对是安全的;
关于Intent的使用要谨慎处理接受的Intent,以及其携带的信息尽量不发送敏感信息,并进行数据校验。
设置Android:exported属性,不需要被外部程序调用的组建应该添加android:exported=”false”属性。
二、Service劫持、拒绝服务。
常见的漏洞有 Java 空指针异常导致拒绝服务和类型转换异常导致的拒绝服务两种。应对 Service 带来的安全问题给大家三点建议:一我们应用在内部尽量使用 Service 设为私有,如果确认这个服务是自己私有的服务,就把它确认为私有,不要作为一个公开的服务;针对 Service 接收到的五数据应该进行校验;内部的Service需要使用签名级别的 protectionle。
传输安全。本地校验用户验证码也非常重要,以后请大家开发中本地的数据校验尽量不要放在本地,尽量放在云端。对于数据的加密,建议所有的App和用户的客户端不要用一个共同的密钥,对于密钥生成的方法尽量根据用户的ID或者一些信息来生成出来,这样避免了大规模密钥的泄露。
第三方组件安全。之前做App应用,在研发后对应用做了很多安全防御。但是大概刚上线不到两天就暴露出漏洞了,究其原因是App项目中用了国内一家非常著名的SDK的推送平台,由于这个平台在发送推送广播的时候没有做数据的校验,导致了黑客可以利用这个推送广播进行伪装,给我发一些数据,最后导致应用在接收了广播之后,只要我点击这个广播应用就崩溃。因此我们除了做好自身应用的安全以外,要保证所引用的第三方,或者合作伙伴也是安全的。也就是说安全是一个团队性的。
Webview的代码执行漏洞。安卓存在一个非常著名的远程代码执行的漏洞,由于我们程序没有正确地使用,大家可能在做GS和Java户调的时候会遇到这个问题,远程攻击者可以通过Java分设接口执行一些恶意的Java方法,最终导致App在使用Webview的时候遭到攻击。我们是可以做一些应对的,安卓系统通过Webview通过一个注册来调用Java功能,攻击者利用反射对他进行攻击,其实谷歌也看到了这个问题,因为这个问题毕竟比较大、也比较广,所以谷歌在API Level17以后这个问题就得到了遏制,对于小于17,或者17以下的能不使用就不使用,如果真的要使用可以增加过滤,对数据的传输做一下校验。
应用安全层。可以对代码进行一些混淆,如配置,如果觉得这还不够,也可以使用一些第三方的工具,比如APK文件。对于更加讲究安全性的经营类的企业,可以选择加固,使用脱壳程序,最后形成一个新的Dex包,最后完成对一个程序的加固。
安全编码规范
其实程序员的编码规范很重要。在Java中,对于一些重要的类、方法、变量,我们在定义的时候一定要想这么几个问题。
- 定义的类或者变量到底返回什么?
- 它们获得什么作为参数?
- 是否能够绕过安全线?
- 它是否含有能够绕过边界,从而绕过保护的方法变量?
有了这种思想之后,对于一些安全性的风险代码为了防止暴露,我们可以做一些操作,说限制对变量的访问,让每个量的方法都成为Final,尽量使你的类不要被克隆,如果一旦允许被克隆,它可能会绕过这个类轻易地复制类的属性。安卓中很多会使用到序列化,如果自己觉得这个类是有风险的,或者说安全性是很高的,尽量不要让它序列化。最后是避免硬编码影响数据。
黑无止境移动安全“漏洞”
知道创宇高级安全顾问锅涛从攻击客的角度看看安全是怎么发生的,未来安全的主战场就在云这一块。未来移动市场肯定会成为我们整个生活的主角,因为移动是主角,就会对移动端安全信息的窃取,以及我们资产的窃取等,有主角的地方就有伤害。我们看到国外安全发展的趋势,尤其是国际上比较知名的Owasp。
从黑客攻击的角度去分析未来攻击主战场,因为硬应用大家通过查阅书籍、网上、社区搜集资料都可以进行多方面的避免。但是黑客攻击的时候,发现攻击想要拿到的数据,就要去平衡一下攻击的成本,如果完全分析带来混淆,我就带来混淆防止别人能够快速分离出代码之间的逻辑。但是黑客也知道你做了大量比较,也就会换思路,就会从一个人的程序设计缺陷的漏洞利用,因为黑客最终是要拿到移动端和最终的核心数据库连接的信息,用户的信息,以及通过缺陷进行资产盗窃。黑客的攻击已经从一个应用发展到了一个逻辑。
黑客在发动任何一次攻击的时候,都有成本。做防护就是为了增加黑客攻击的成本,无论是做代码混淆还是加固,成本提高了黑客有可能就会放弃攻击,但是他会寻找新的突破口。这就是下面要跟大家说的移动端里面业务逻辑设计缺陷,为什么业务逻辑设计缺陷会成为未来的一个主要的方向。
- 应用逻辑是神一般地存在,老的程序员也是在劫难逃,因为业务的发展造成了程序员没法快速地去准备代码。
- 安全开发人员也不能安全避免应用设计缺陷。
- App本身的漏洞,一半的比例在业务漏洞上,而自己的逻辑漏洞没有一个自动化的程序促使全员去发现它。
- 业务逻辑漏洞利用的就是开发人员本身人的缺陷,造成了它逃逸于各种防护,无论是代码混淆、加固等等。
业务逻辑漏洞之所以会出现是因为业务发展迅速、开发水平不一、第三方缺陷、内部监管不严格也会出现这种漏洞发生。业务逻辑漏洞最常见的就是账号登陆限制的问题。还有安全性的问题,也会发现密码重置,还有的是采用手机号+我的验证码,就造成了黑客可以利用验证码进行破解,以及常见的另一种安全问题是App端的客户端应用。
随着我们业务的发展,发现在金融行业,以及在我们的社交领域另一种手势密码。手势密码安全其实还是可以的,但是手势密码有很多解锁,可以通过多种方式去对手势密码进行一个修改。最常见的有暴力破解,以及去修改这一个文件重置本地手势密码。
-
App安全之网络传输安全问题
2016-09-29 15:22:26App安全之网络传输安全问题 字数4865 阅读132 评论1 喜欢1 App安全之网络传输安全问题 移动端App安全如果按CS结构来划分的话,主要涉及客户端本身数据安全,Client到Server网络传输的安全,客户端本身... -
spring 线程安全问题
2018-09-11 23:18:28一直有个疑惑,spring是怎么处理自己的线程安全问题的呢,这里简单说明下。 1、介绍两个概念 有状态的bean:对象中有实例变量(成员变量),可以保存数据,是非线程安全的。 无状态的bean:对象中没有实例变量... -
Jackson线程安全问题
2019-11-05 12:12:05Jackson线程安全问题 参考文章 How do I correctly reuse Jackson ObjectMapper? How correctly and thread safe reuse Jackson ObjectReader? Should I declare Jackson’s ObjectMapper as a static field? Why ... -
App的安全问题
2016-05-07 14:38:59App的安全问题 -
Spring线程安全问题
2018-05-14 09:48:14但其实,Spring并没有保证这些对象的线程安全,需要由开发者自己编写解决线程安全问题的代码。 Spring对每个bean提供了一个scope属性来表示该bean的作用域。它是bean的生命周期。例如,一个scope为singleton的bean,... -
车联网的信息安全问题及安全威胁
2019-04-21 22:04:59之前听过一位老师对车联网的讲述,对此十分感兴趣,因此查询了关于车联网的安全问题方面的资料。 1.车联网的信息安全问题 车联网和物联网相似,在应用中,每辆车及其车主的信息都将随时随地连接到网络随时随地被... -
面试题:线程安全问题
2019-04-24 21:38:53一、为什么会有线程安全问题? 当多个线程同时共享同同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读的操作不会发生线程安全问题。 二、如何解决多线程之间线程安全... -
Java多线程安全问题和锁
2020-02-28 17:32:26多线程安全问题和锁 文章目录多线程安全问题和锁线程在jvm中的特点锁的出现synchronized 关键字-监视器锁monitor lock死锁的产生和避免 什么是线程安全问题? 当多个线程同时操作同一个数据是,可能会出现数据不一样... -
前端安全问题及解决办法
2019-02-25 00:07:25一、随着前端的快速发展,各种技术不断更新,但是前端的安全问题也值得我们重视,不要等到项目上线之后才去重视安全问题,到时候被黑客攻击的时候一切都太晚了。 二、本文将讲述前端的六大安全问题,是平常比较常见... -
如何解决线程安全问题
2019-04-14 15:52:37什么是线程安全问题? 当多个线程共享一个全局变量,对其做写操作时,可能会受到其他线程的干扰,从而引发线程安全问题 内置锁(synchronized) 内置锁也叫互斥锁,可以保证线程的原子性,当线程进入方法时,会自动... -
02 | 安全原则:我们应该如何上手解决安全问题?
2020-08-19 16:43:16上一讲,我们一起拆解学习了 CIA 三元组,也就是机密性、完整性和可用性。...面试官点点头,接着说道:“你觉得该怎么去解决安全问题呢?” 毫无疑问,不同的应用、不同的模块会受到不同的安全威胁,当然,我们面. -
Web站点常见安全问题
2017-02-06 13:51:15Web站点常见安全问题类型 -
常见的 App 安全问题
2016-12-23 15:32:36常见的 App 安全问题 据2015年第三季度移动安全报告显示,Android 16个行业 TOP 10 应用漏洞类别和数量中,Webview远程代码执行占到了第一位,第二位是Webview文明存储密码。这些领域涵盖大家平时工作领域,我们... -
安全测试===8大前端安全问题(下)
2018-11-28 11:37:03在《8大前端安全问题(上)》这篇文章里我们谈到了什么是前端安全问题,并且介绍了其中的4大典型安全问题,本篇文章将介绍剩下的4大前端安全问题,它们分别是: 防火防盗防猪队友:不安全的第三方依赖包 用了... -
servlet是否存在线程安全问题
2018-06-12 21:21:33今天老师问了一句,servlet存在线程安全问题吗,心想着servlet不是单例的嘛,每个线程在调用的时候都会为实例对象分配独立的引用。我就以为servlet属于线程安全的。晚上自己再网上查看了一下,发现servlet不是安全的... -
SimpleDateFormat线程安全问题详解
2018-11-03 10:17:44SimpleDateFormat线程安全问题详解 在平时的工作中,我们经常需要将日期在String和Date之间做转化,此时需要使用SimpleDateFormat类。使用SimpleDateFormat类的parse方法,可以将满足格式要求的字符串转换成Date... -
Spring解决单例bean线程不安全问题
2019-05-27 17:32:11首先我们应该知道线程安全问题一般发生在成员变量上,这是为什么啦? 因为成员变量是存放在堆内存中,而堆内存又是线程共享的,这就造成了线程安全问题 因为Spring中的Bean默认是单例的,所以在定义成员变量时也... -
Java并发编程-集合类的线程安全问题
2021-01-15 16:59:331.List集合的线程安全问题 1.ArrayList线程安全问题。 ArrayList是线程安全的吗,我们不妨运行以下的程序 public static void main(String[] args) { // TODO Auto-generated method stub List<String> ... -
Java web应用中的安全问题整理
2017-09-10 09:19:13背景几年前在CSDN的C币商城换购过一本《白帽子讲Web安全》,了解过Web网站在渗透测试过程中常见的安全问题。近来,自己开发的Java Web应用中存在一些安全漏洞,被迫要求关注这些安全隐患、并加固。那么本文就顺便... -
mysql与redis安全问题
2016-10-30 18:02:57作为网络服务的中心,网络...常见服务的安全问题: 1、redis服务; 2、mysql服务; redis服务所存在的潜在安全问题: redis crackit 漏洞利用实例; 由于很多reids服务都是免密码登录的, 连接无密码认证的reids服务 -
Web 开发常见安全问题
2016-03-01 19:46:11这就是这篇科普文章的存在意义,希望 Web 开发者在开发时能依此逐条检查代码中的安全问题。 注:服务器运维相关的安全注意事项不在本文之列 这篇文章主要包含以下内容: 前端安全 XSS 漏洞CSRF 漏洞 后端安全... -
jsonp跨域的安全问题
2017-04-24 09:40:121、Callback可自定义导致的安全问题Content-type与XSS漏洞 再输出 JSON 时,没有严格定义好 Content-Type( Content-Type: application/json )然后加上 callback 这个输出点没有进行过滤直接导致了一个典型的 X -
ArrayList 线程安全问题
2019-03-21 17:33:39皆会说明, ArrayList与HashMap类型都不是线程安全的. 那么,在传统的集合包内的集合类到底为什么线程非安全呢?在新的JUC包类又有什么可以替代呢? 让我们开始今天的部分. 本章主要包括如下几个部分: 为什么ArrayList... -
线程安全问题及解决方法
2017-03-04 17:13:36(1)多线程安全问题的原因(也是我们判断一个程序是否有线程安全问题的依据) A:是否有多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 (2)如何解决多线程安全问题呢? 基本思想:让程序没有安全... -
SaaS应用选型,必须考虑的10个安全问题
2020-01-13 18:11:53SaaS模式下,企业用户...本文整理了10个必问的SaaS安全问题,包括基础安全,应用安全,安全合规、数据安全、安全责任划分等方面,可以快速了解SaaS厂商的安全能力。 1、SaaS软件的部署方式? A、是否支持私有化...