std string与线程安全_正确理解线程安全与非线程安全

引言

有没有常被人问到以下几个问题:

ArrayList和Vector有什么区别?

HashMap和HashTable有什么区别?

StringBuilder和StringBuffer有什么区别? 每当听到这样的问题时,答案则无非是来自‘XX面试宝典’的那几句:

ArrayList是非线程安全的,Vector是线程安全的

HashMap是非线程安全的,HashTable是线程安全的

StringBuilder是非线程安全的,StringBuffer是线程安全的 突然发现我们平时用的基本都是非线程安全的,甚至线程安全的有人从来没用过。那么我们是否写的程序都存在安全问题,下面我们将就安全进行一个解释。

安全问题的暴露

在高并发的场景下,我们会利用java的多线程特性提高效率。当多个线程共享一个资源的时候,则会出现是否安全的问题。例如以下代码关于ArrayList的使用场景,我们假设有这么一个线程

package cn.buglife.learn.thread;

import java.util.List;

import java.util.UUID;

import java.util.concurrent.CountDownLatch;

/**

* 定义一个线程(往给定的列表添加100个数据)

*

* Created by zhangjun on 16/6/23.

*/

public class LearnThread implements Runnable {

private List resource;

private CountDownLatch countDownLatch;

public LearnThread(List resource, CountDownLatch countDownLatch) {

this.resource = resource;

this.countDownLatch = countDownLatch;

}

@Override

public void run() {

for (int i = 0; i < 100; i++) {

resource.add(UUID.randomUUID().toString());

}

countDownLatch.countDown();

}

}

接下来我们启动100个线程去帮助我们完成资源的录入,理论期望应该资源数组大小为10000

package cn.buglife.learn.thread;

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.CountDownLatch;

/**

* Created by zhangjun on 16/6/23.

*/

public class ThreadSafe {

public static void main(String[] args) {

List unSafeList = new ArrayList();

//启动100个线程

int threadCount = 100;

CountDownLatch countDownLatch = new CountDownLatch(threadCount);

for (int i=0; i

Thread thread = new Thread(new LearnThread(unSafeList,countDownLatch));

thread.start();

}

try {

countDownLatch.await();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.print(unSafeList.size());

}

}

执行上述程序5次得到的结果如下

资源大小

耗时

9999

119

10000

115

9999

119

9999

114

9999

117

若使用线程安全的Vector呢?

package cn.buglife.learn.thread;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

import java.util.Vector;

import java.util.concurrent.CountDownLatch;

/**

* Created by zhangjun on 16/6/23.

*/

public class ThreadSafe {

public static void main(String[] args) {

Long time = new Date().getTime();

List safeList = new Vector();

//启动100个线程

int threadCount = 100;

CountDownLatch countDownLatch = new CountDownLatch(threadCount);

for (int i=0; i

Thread thread = new Thread(new LearnThread(safeList,countDownLatch));

thread.start();

}

//主线程等待其他线程全部执行完再执行

try {

countDownLatch.await();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("资源大小:"+safeList.size());

System.out.print("耗时:"+(new Date().getTime()-time));

}

} 上述代码执行结果:

资源大小

耗时

10000

112

10000

118

10000

105

10000

123

10000

125

如何选择

根据以上现象可以看出,非线程安全的ArrayList结构会在多线程使用的过程中随机性得使计算错乱,那么是不是非线程安全得数据结构就不要用了呢?

非线程安全是指多线程操作同一个对象可能会出现一些误差问题。而

线程安全则是指多线程操作同一个对象不会出现问题。 那么又有一个新得问题,是不是非线程安全得是不是就不能在多线程环境下使用了?答案是No,我们需要明确得是:

线程安全问题是针对多线程环境下,多个线程操作同一个对象

鱼和熊掌不可兼得,线程安全得代价就是性能相对得有所下降

非线程安全得对象在独立线程内是不存在问题得

结论 线程安全与非线程安全取决于应用得环境,是取是舍需要根据所处环境决定,切勿盲目下结论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值