什么是线程安全以及threadlocal为什么是线程安全的
来源:互联网 发布:北京科瑞明软件招聘 编辑:程序博客网 时间:2024/04/30 23:52
什么是线程安全?
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
线程安全就是说多线程访问同一代码,不会产生不确定的结果。编写线程安全的代码是依靠线程同步。
产生不确定 结果的例子:
定义一个共享数据:
public static int a = 0;多线程多该共享数据进行修改:
private static void plus() { for (int i = 0; i < 10; i++) { new Thread() { public void run() { a++; try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("plus:" + Thread.currentThread().getName() + ": " + a); } }.start(); }}输出结果:
plus:Thread-5: 5plus:Thread-2: 5plus:Thread-6: 5plus:Thread-9: 5plus:Thread-1: 6plus:Thread-0: 8plus:Thread-4: 8plus:Thread-3: 10plus:Thread-7: 10plus:Thread-8: 10很明显,在第一次输出a的值的时候,a的值就已经被其他线程修改到5了,显然线程不安全。
产生确定结果的例子:
利用synchronized关键字将修改a值的地方和输出的地方上锁。让这段代码在某一个时间段内始终只有一个
线程在执行:
private static void plus() { for (int i = 0; i < 10; i++) { new Thread() { public void run() { synchronized (JavaVariable.class) { a++; try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("plus:" + Thread.currentThread().getName() + ": " + a); } } }.start(); }}输出结果:
plus:Thread-2: 1plus:Thread-6: 2plus:Thread-7: 3plus:Thread-3: 4plus:Thread-8: 5plus:Thread-4: 6plus:Thread-0: 7plus:Thread-9: 8plus:Thread-5: 9plus:Thread-1: 10结果正确。
为什么threadlocal是线程安全的?
首先定义一个ThreadLocal。
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() { protected Integer initialValue() { return 0; }};插一句题外话:为什么threadLocal要被声明成静态的?
这是为了多个线程使用同一个ThreadLocal对象。
private static void plus() throws Exception { for (int i = 0; i < 10; i++) { new Thread() { public void run() { //1 a = threadLocal.get(); a++; //2 threadLocal.set(a); System.out.println("plus:" + Thread.currentThread().getName() + ": " + threadLocal.get()); } }.start(); }}
它的结果是怎样呢?
全部会输出1。当然,它无法使多个线程共同修改一个值,并且保持这个值递增。因为threadlocal不是做这个的,它是为了隔离数据的共享,而不是像同步机制一样实现线程间的通信。
但它的结果是可以确定的,所以它是线程安全的。
很明显,在代码“1”的时候,每一个线程都会将threadLocal的初始值0赋值给共享变量a,因为每一个线程从threadLocal.get()拿到的值都是自己threadLocal保存的。所以,就没有所以了。
所以对于共享变量a来讲,每个线程都会首先将自己threadLocal里面的初始值0赋值给a,然后将共享变量a+1,然后将a+1的值设置到自己的ThreadLocalMap中,其他线程就访问不到了。下一个线程来的时候又会将自己threadLocal里面的初始值0赋值给a,然后将 a+1,然后... 如此周而复始。a只是被在0和1之间改来改去,最终放到每一个线程的threadLocal里面的a+1的值就不再共享。
- 什么是线程安全以及threadlocal为什么是线程安全的
- 什么是线程安全? 线程安全是怎么完成的(原理)?
- 为什么jdbctemplate是线程安全的
- java Timer为什么是线程安全的
- 为什么jdbctemplate是线程安全的
- java线程安全的ThreadLocal
- j2ee的线程安全--threadlocal
- 线程安全---ThreadLocal
- threadLocal线程安全介绍
- ThreadLocal线程安全
- ThreadLocal实现线程安全的经典例子
- ThreadLocal保证线程安全的原理
- SimpleDateFormat的线程安全和ThreadLocal
- SpringMVC和Struts是线程安全的吗?为什么?
- SpringMVC和Struts是线程安全的吗?为什么?
- Java:什么是线程安全
- 什么是线程安全?
- 什么是线程安全
- Linux下性能分析工具和内存泄露检测工具的简介(Valgrind和gprof)
- Java 中的引用
- 为什么需要NOSQL
- FFmpeg获取视频的旋转角度rotate函数,一定能获取!(要放在解析视频流的时候才能获取)
- 动态规划入门
- 什么是线程安全以及threadlocal为什么是线程安全的
- Data到DOM,DOM到data,两个变量,我们都要互相监听
- 5.适配器模式
- cocos2d-x 有关Node
- 熊猫TV 弹幕助手 (开源 、 Java)
- java InputStream读取数据问题(转)
- Java常见日期格式及日期的计算工具类
- uva10026 - Shoemaker's Problem
- audio filter adelay 实现音量 延迟(空白音)(笔记)