什么是线程安全的(thread-safe)? html
在java中,线程安全的指的是代码能够在并发的或者多线程的环境下安全的使用或者共享,而且它们都将按照指望的方式运行。任何代码,类或者对象,若是它们在并发的环境中运行表现出的行为与在非并发环境下表现出的行为不一致,那么它们就不能被称为线程安全的。 java
本片文章不会很是仔细的介绍线程安全或者Java中的异步处理,咱们将经过几个例子来帮助你理解什么是线程安全的而后告诉你如何让你的代码线程安全。 缓存
一个non-thread-safe的例子 安全
public class Counter { private int count; /* * 这个方法不是线程安全的,由于++操做不是原子操做 */ public int getCount(){ return count++; } }上面的例子不是线程安全的,由于++(自增操做)不是一个原子操做(atomic operation),而是会被拆分红读、更新和写操做(read,update,write)三部分,若是多个线程大约在同一时刻调用getCount()方法,这三个操做可能会互相重合(coincide)或者重叠(overlap),好比:当thread1正在更新数据,thread2此时读取数据,那他将会得到原来的旧数据,最后的结果就是thread2会覆盖掉thread1对数据的增长操做,结果就是:一个数据被丢失了,就是由于程序是并发调用的。
如何在Java中实现线程安全? 多线程
要使上面的方法线程安全,能够有不少种方式: 并发
1)使用synchronized关键字来锁定getCount方法,以保证同一时刻只有一个线程能够访问getCount方法,这样作就能避免重合(coincide)或者重叠(overlap)问题。 异步
2)使用AutomicInteger,这样就将++变成了原子操做,由于原子操做是线程安全的,这样作还节省了额外的同步操做的开销。 ide
下面是一个实现线程安全的例子: 优化
public class Counter { private int count; AtomicInteger atomicCount = new AtomicInteger( 0 ); /* * 如今这个方法是线程安全的,由于增长了synchronized */ public synchronized int getCount(){ return count++; } /* *这个方法是线程安全的,由于count的增长操做是原子操做 */ public int getCountAtomically(){ return atomicCount.incrementAndGet(); } }关于Thread-Safe的一些重要的点:
这些点在你写线程安全的程序的时候是颇有用的,并且也能帮你避免一些很严重的并发问题,好比:竞争条件(race condition)或者死锁 atom
1)不可变的对象(immutable objects)默认就是线程安全的,由于它们的状态一旦建立就不能被改变。因为字符串在Java中就是不可变的,因此它们本来就是线程安全的(关于不可变对象,后期会有相关文章进行说明)。
2)只读的或者被final修饰的变量也是线程安全的。
3)锁机制在Java中是一种实现线程安全的方式。
4)静态变量若是没有被正确的synchronized,那么它将成为线程安全问题的主要缘由。
5)Java中的一些线程安全的例子:Vector, Hashtable, ConcurrentHashMap, String等。
6)Java中的原子操做是线程安全的,好比从内存中读取一个32位的int值是线程安全的,由于它是原子操做,因此不会与其余线程交错。
7)局部变量也是线程安全的,由于每个线程都会有属于她本身的一份拷贝。使用局部变量是一种很好的实现线程安全的方式。
8)为了实现线程安全,尽量地减小多个线程中对象的共享。
9)volatile关键字能够用来指示线程不缓存该变量而是直接从主内存中读取,也能够指示JVM不从多线程的角度来从新排序或者优化代码(not to reorder or optimize code from threading perspective)。
以上就是本文介绍的一些内容。
线程安全是一个比较难以掌握的概念,为了肯定程序是否线程安全你须要考虑多并发的状况,另外JVM为了会对代码进行优化,而优化的过程就会涉及到对代码的从新排序,因此看起来是串行的程序在开发环境中运行良好,但并不能保证在生产环境中会一样良好,由于JVM会尽最大可能的进行调整,从而进行一些代码重排序和优化,这样就会致使线程安全的问题。
参考资料:http://javarevisited.blogspot.com/2012/01/how-to-write-thread-safe-code-in-java.html
----------------------------------------------------------------
小人不才,若有问题,欢迎各位不吝赐教!