版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qwkxq/article/details/57110587
java中包含几种线程级别:
不可变:这种级别是最简单的线程安全方式,即:如果带有状态的变量是基本数据类型定义成final,是引用类型,则其对象不能有改变自身的行为
(如String,enum,Number的部分子类:Integer,Long等[不包括AtomicInteger,AtomicLong等])
绝对安全:不论运行环境如何,调用者都不需要任何额外的措施来保证线程安全,要想达到这点,可能会付出巨大的代价。
相对安全:对对象的单独操作是线程安全的(如上面多线程访问remove方法,add方法),但对于特定顺序的连续调用,就需要调用者使用额外的同步手段来保证线程安全。
以java.util.Vector举例,在java中称它为线程安全的对象,这是因为Vector中所有的行为都被synchronized修饰,这也是java通俗意义上讲的线程安全的概念,然而Vector实际上只是线程相对安全的,并非绝对安全,在涉及特定顺序的连续调用就会出现问题:
/*
此程序先对Vector初始化1000个元素,然后每次开启2个线程,1个线程执行删除元素操作,1个线程执行获取元素操作。
当一个错误的时机(获取线程进入for循环执行到当前Vector的size-x时,被删除线程抢走执行权删除了x个或以上的元素)
此时获取线程才得到执行权,结果此前的Vector的长度已经不够size-x,就会导致角标越界异常。
*/
private static Vector<Integer> v = new Vector<>();
static{
for(int i=0; i<1000; i++){
v.add(i);
}
}
public static void main(String[] args) {
while(true){
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i<v.size(); i++){
v.remove(i);
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i<v.size(); i++){
v.get(i);
}
}
}).start();
//不要产生过多的线程,防止操作系统假死
if(Thread.activeCount()>20)break;
}
}
线程兼容:指对象本身不是线程安全的,但是调用者可以通过正确的同步手段来保证线程安全,也就是我们通常说的线程不安全。
线程对立:指对象无论是否采用同步操作,都无法在多线程中并发使用的代码,由于java天生具备多线程特性,这种情况很少见,且通常是有害的,应当尽量避免。
(常见的有Thread对象的resume方法和suspend方法[已废弃],System的setIn,setOut,runFinalizersOnExit)