线程安全理解
一.线程安全示意图
其中锁1,锁2表示该对象对应的类中某些具有锁功能的代码块,方法等。
如果锁1,锁2都是传统锁(synchronized)的话,
线程1.线程2,线程3,线程4,线程5之间都是互斥的,任何一个线程在执行,其他的线程都在等待。
二.线程安全的检测
在程序中,当一个类在没有做锁处理的情况,它的实例被多个线程共享时,就会可能存在线程安全问题。
分析的一般步骤的思路(也有其他特殊情况),作为参考:
第一步:在类的构造方法加上打印日志语句
第二步:在类的方法都加上 System.out.println(Thread.currentThread().getName());
第三步: 启动主线程,或者其他操作触发多线程(如web项目,我们一个请求就是触发一个线程)
第四步: 分析类的构造方法上日志是否打印一遍,而类的方法上日志打印多遍,且线程名称存在不同。这就是说明多个线程对同一个对象进行操作。
第五步:考虑线程安全,是否需要对这些方法(或者方法里的代码块)进行加锁处理。哪里加锁,加什么样的锁,锁的粒度等等,这样就需要根据具体
情况具体分析,然后结合多线程的知识,测试的情况进行完善。
如果是多个线程共同调用同一个静态方法,那么如果考虑到线程安全就要用该类的字节码(****.class)作为锁来使用。
所以要想让一个进程的线程产生共享,不管他们在什么地方,要让他们共享对象,或者共享类的静态属性和方法。
要想使之安全,互斥,就得加锁处理。
方法区,Java堆是对所有线程共享的,只是有的时候在某个线程中想要获取对象的实例,找不到引用的句柄,所以要想共享,就把该对象的引用传递到另一个线程里使用。
java虚拟机栈的理解:每一个线程的栈帧都是独立私有的,都有各自独立的栈帧机构(局部变量表,操作数栈,动态连接方法,返回地址),只有他们访问同一个对象,
类的static元素时才会需要做互斥处理。
java 对象锁可以是任何对象锁。