给“线程安全”下定义是件很是棘手的事儿。随便Google一下,就能获得成千上万像这样的定义:html
1.“线程安全”的代码是指在多线程同时执行的状况下,依然能正常工做的代码。java
2.一段代码,若是在多线程同时执行的状况下,能以一种安全的方式操做共享数据结构,它就是线程安全的。安全
还有不少相似的定义。数据结构
你不觉着相似上面这种定义非但没有传达出有用的信息,甚至让本身更加迷惑吗?尽管这样,这些定义仍是被你们无奈的接受了,由于它并无错。只是,他们没能提供任务实质性的帮助或看法。多线程
咱们怎么区别“线程安全”的类和不安全的类?甚至说“安全”到底什么意思?并发
在线程安全中,什么是“正确性”?less
任何对“线程安全”的合理定义,其核心都是在说“正确性”的概念。因此在理解线程安全以前,咱们先来搞懂什么是“正确性”。post
正确性意味着一个类要符合它的规范
一个好的类规范会明确规定出类在某个时刻的状态,以及对它进行一些操做后的后置条件(postcondition)。可是,一般咱们并不能为咱们的类提供充分的规范说明,那咱们怎么知道他们是否正确执行了?咱们并不能知道,可是这并不能阻止咱们去使用它,一旦咱们说服了本身“这些代码能正确工做”。这种“代码信任”就很是接近咱们要说的“正确性”。学习
如今咱们能够给“线程安全”下一个不那么绕的定义:线程
一个类在多线程并发访问时仍能保证行为的正确性,那么它就是线程安全的类。
一个线程安全的类在被多线程并发访问时仍然能正确的执行,无论这些线程是顺序执行仍是错终复杂的交叉执行。而且,被调用的代码中不须要额外的添加线程同步代码。
换句话说,线程安全的类在多线程环境下和单线程环境下运行结果老是一致的。线程安全的类在内部已经处理好了任何有关线程同步的问题,而调用者再也不须要考虑线程安全问题。
例子:无状态的Servlet
关于线程安全的类有个很好的例子,就是没有全局变量的java Servlet。这样的Servlet是无状态的。
public class StatelessFactorizer implements Servlet { public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = factor(i); encodeIntoResponse(resp, factors); } }
StatelessFactorizer类每次执行后的瞬时状态只存在于service方法的局部变量中,而局部变量存储在线程私有的线程栈中。一个线程访问StatelessFactorizer不会影响到另外一个线程访问StatelessFactorizer的结果,由于这两个线程没有共享状态,就好像他们在访问不一样的实例。因为,一个线程对无状态对象的操做不会影响到其余线程的操做的正确性,因此无状态对象是线程安全的。
以上就是很重要的“线程安全”的概念。
学习愉快!