论坛首页 Java企业应用论坛

简明扼要,再谈ThreadLocal和synchronized

浏览 23027 次
该帖已经被评为良好帖
作者 正文
   发表时间:2008-04-08  
spiritfrog 写道
感觉这样解释反而变得有些麻烦了,直接看下源码倒简单些。
横向的实际上是,同一个线程a中,三个threadlocal对象保存x,y,z,实际上在a线程的map中,以threadlocal对象为key保存x,y,z
纵向的,说的是不同线程的情况,分别用threadlocal保存对象x,结果每个线程的map都保存了x。实际上这个x也是不安全的,因为三个线程都能访问它,如果能修改的话。


楼上的,对纵向的理解是不对的。
变量x对于线程而言是安全的,而非不安全的。如果X是java的原生类型,则在每个线程中存在的是X的值副本;如果X是对象类型,那么每个线程中的对象引用也是不同的,因为对方法中的X的值改变,只影响当前X的引用(或者说指针的指向),不会影响其他线程的副本值,这也是所谓副本的含义。你可以做个实验。

0 请登录后投票
   发表时间:2008-04-08  
linliangyi2007 写道


楼上的,对纵向的理解是不对的。
变量x对于线程而言是安全的,而非不安全的。如果X是java的原生类型,则在每个线程中存在的是X的值副本;如果X是对象类型,那么每个线程中的对象引用也是不同的,因为对方法中的X的值改变,只影响当前X的引用(或者说指针的指向),不会影响其他线程的副本值,这也是所谓副本的含义。你可以做个实验。


当x是对象类型时,X必须是逃逸型引用,而不能是非逃逸型引用,即X是通过在本地方法中产生的,这就是所谓local的含义。如果X是非逃逸型的,则仍然有同步问题。
比如:
class A{
    private Object v;
    public A(){
        v=new Object();
    }
    public ThreadLocal method1(){
        ThreadLocal local=new ThreadLocal();
        local.set(v); //对象v是非逃逸型引用,这儿的local所引用的对像是非同步安全的
        return local;
    }
    public ThreadLocal method2(){
        ThreadLocal local = new ThreadLocal();
        local.set(new Object()); //这儿的值是逃逸类型的,因此local是同步安全的
        return local;
    }
    public void methodUseLocal(){
        ThreadLocal local1=method1();
        Object tempv1=local1.get(); //这儿的tempv1其实就是this.v,因此是非线程安全的
        //...
        ThreadLocal local2=method2();
        Object tempv2=local2.get(); //这儿的tempv2是线程安全的,是和当前线程绑定的变量
        //...
    }
}
0 请登录后投票
   发表时间:2008-04-08  
rehte 写道
linliangyi2007 写道


楼上的,对纵向的理解是不对的。
变量x对于线程而言是安全的,而非不安全的。如果X是java的原生类型,则在每个线程中存在的是X的值副本;如果X是对象类型,那么每个线程中的对象引用也是不同的,因为对方法中的X的值改变,只影响当前X的引用(或者说指针的指向),不会影响其他线程的副本值,这也是所谓副本的含义。你可以做个实验。


当x是对象类型时,X必须是逃逸型引用,而不能是非逃逸型引用,即X是通过在本地方法中产生的,这就是所谓local的含义。如果X是非逃逸型的,则仍然有同步问题。
比如:
class A{
    private Object v;
    public A(){
        v=new Object();
    }
    public ThreadLocal method1(){
        ThreadLocal local=new ThreadLocal();
        local.set(v); //对象v是非逃逸型引用,这儿的local所引用的对像是非同步安全的
        return local;
    }
    public ThreadLocal method2(){
        ThreadLocal local = new ThreadLocal();
        local.set(new Object()); //这儿的值是逃逸类型的,因此local是同步安全的
        return local;
    }
    public void methodUseLocal(){
        ThreadLocal local1=method1();
        Object tempv1=local1.get(); //这儿的tempv1其实就是this.v,因此是非线程安全的
        //...
        ThreadLocal local2=method2();
        Object tempv2=local2.get(); //这儿的tempv2是线程安全的,是和当前线程绑定的变量
        //...
    }
}



楼上提醒的是。实际上,我们对于一个方法是用ThreadLocal来对本地变量进行副本的时候,大多指的是方法内部变量(请看我的示意图,X是方法内部的local varible)。要对类变量进行共享的话,不是ThreadLocal设计的目的。
但确实存在这样的问题,值得大家注意。
0 请登录后投票
   发表时间:2008-04-11  
linliangyi2007 写道
rehte 写道
linliangyi2007 写道


楼上的,对纵向的理解是不对的。
变量x对于线程而言是安全的,而非不安全的。如果X是java的原生类型,则在每个线程中存在的是X的值副本;如果X是对象类型,那么每个线程中的对象引用也是不同的,因为对方法中的X的值改变,只影响当前X的引用(或者说指针的指向),不会影响其他线程的副本值,这也是所谓副本的含义。你可以做个实验。


当x是对象类型时,X必须是逃逸型引用,而不能是非逃逸型引用,即X是通过在本地方法中产生的,这就是所谓local的含义。如果X是非逃逸型的,则仍然有同步问题。
比如:
class A{
    private Object v;
    public A(){
        v=new Object();
    }
    public ThreadLocal method1(){
        ThreadLocal local=new ThreadLocal();
        local.set(v); //对象v是非逃逸型引用,这儿的local所引用的对像是非同步安全的
        return local;
    }
    public ThreadLocal method2(){
        ThreadLocal local = new ThreadLocal();
        local.set(new Object()); //这儿的值是逃逸类型的,因此local是同步安全的
        return local;
    }
    public void methodUseLocal(){
        ThreadLocal local1=method1();
        Object tempv1=local1.get(); //这儿的tempv1其实就是this.v,因此是非线程安全的
        //...
        ThreadLocal local2=method2();
        Object tempv2=local2.get(); //这儿的tempv2是线程安全的,是和当前线程绑定的变量
        //...
    }
}



楼上提醒的是。实际上,我们对于一个方法是用ThreadLocal来对本地变量进行副本的时候,大多指的是方法内部变量(请看我的示意图,X是方法内部的local varible)。要对类变量进行共享的话,不是ThreadLocal设计的目的。
但确实存在这样的问题,值得大家注意。

方法内部变量 还用担心线程安全问题吗?
当然是类变量才需要担心了。

不太明白那个逃逸型非逃逸型是什么意思,
例子里面那个逃逸类型,及方法内部变量,没有线程安全问题,
非逃逸类型,用了ThreadLocal,自然也就安全了。
0 请登录后投票
   发表时间:2008-04-11  
xieke 写道
linliangyi2007 写道
rehte 写道
linliangyi2007 写道


楼上的,对纵向的理解是不对的。
变量x对于线程而言是安全的,而非不安全的。如果X是java的原生类型,则在每个线程中存在的是X的值副本;如果X是对象类型,那么每个线程中的对象引用也是不同的,因为对方法中的X的值改变,只影响当前X的引用(或者说指针的指向),不会影响其他线程的副本值,这也是所谓副本的含义。你可以做个实验。


当x是对象类型时,X必须是逃逸型引用,而不能是非逃逸型引用,即X是通过在本地方法中产生的,这就是所谓local的含义。如果X是非逃逸型的,则仍然有同步问题。
比如:
class A{
    private Object v;
    public A(){
        v=new Object();
    }
    public ThreadLocal method1(){
        ThreadLocal local=new ThreadLocal();
        local.set(v); //对象v是非逃逸型引用,这儿的local所引用的对像是非同步安全的
        return local;
    }
    public ThreadLocal method2(){
        ThreadLocal local = new ThreadLocal();
        local.set(new Object()); //这儿的值是逃逸类型的,因此local是同步安全的
        return local;
    }
    public void methodUseLocal(){
        ThreadLocal local1=method1();
        Object tempv1=local1.get(); //这儿的tempv1其实就是this.v,因此是非线程安全的
        //...
        ThreadLocal local2=method2();
        Object tempv2=local2.get(); //这儿的tempv2是线程安全的,是和当前线程绑定的变量
        //...
    }
}



楼上提醒的是。实际上,我们对于一个方法是用ThreadLocal来对本地变量进行副本的时候,大多指的是方法内部变量(请看我的示意图,X是方法内部的local varible)。要对类变量进行共享的话,不是ThreadLocal设计的目的。
但确实存在这样的问题,值得大家注意。

方法内部变量 还用担心线程安全问题吗?
当然是类变量才需要担心了。

不太明白那个逃逸型非逃逸型是什么意思,
例子里面那个逃逸类型,及方法内部变量,没有线程安全问题,
非逃逸类型,用了ThreadLocal,自然也就安全了。


说的自己都晕了,一句话,ThreadLocal不是专门为线程安全而设计的,更多是为了变量的共享。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics