
线程安全定义
- 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的
原子性
- 程序作为不可分割的一部分,也就是说在执行该程序的过程中其他线程要处于等待状态
竟态条件
- 当某个计算的正确性取决于多个线程的交替执行时序时,那么就会发生静态条件。
列子:一段程序有两个步骤A,B A中的值对B产生影响,如果两个线程U该执行完A,在要去执行B过程中,线程W修改了A中结果的数值,此时U中B执行的结果是错误的
复合操作
- 为了避免竟态条件的问题,就必须在某个线程修改该变量值时,需要通过某种方式防止其他线程使用这个变量。
要解决上边例子的问题,必须保证U在执行的过程中不该程序不能被其他线程多影响
加锁机制
- 目的为了实现程序的原子性
内置锁
-
同步代码块
123synchronized(lock){} -
重入
机制:每个锁都关联一个请求计数器和一个占有他的线程,当请求计数器为0时,这个锁可以被认为是unhled的,当一个线程请求一个unheld的锁时,JVM记录锁的拥有者,并把锁的请求计数加1,如果同一个线程再次请求这个锁时,请求计数器就会增加,当该线程退出syncronized块时,计数器减1,当计数器为0时,锁被释放。
java锁的可重入性机制可以解决下面这个问题123456789101112public class Widget {public synchronized void doSomething() {...}}public class LoggingWidget extends Widget {public synchronized void doSomething() {System.out.println(toString() + ": calling doSomething");super.doSomething();}}
如果没有Java锁的可重入性,当一个线程获取LoggingWidget的doSomething()代码块的锁后,这个线程已经拿到了LoggingWidget的锁,当调用父类中的doSomething()方法的时,JVM会认为这个线程已经获取了LoggingWidget的锁,而不能再次获取,从而无法调用Widget的doSomething()方法,从而造成死锁。从中我们也能看出,java线程是基于“每线程(per-thread)”,而不是基于“每调用的(per-invocation)”的,也就是说java为每个线程分配一个锁,而不是为每次调用分配一个锁。
http://blog.csdn.net/dayuguohou2008/article/details/6660179




近期评论