关于线程的问题,清高手指点

对于线程我有以下的理解,不知是否正确,请高手指点一下:
1、只要类或者类的方法没有使用公共变量,则这个类或类的方法就是线程安全的。就不需要同步。
2、入上所说得类如果是安全的,那么多个线程同事调用这个类的唯一实例和多个线程调用这个类的线程池中的实例,有什么不同,那个更好?(以上的想法是基于“每当调用类的方法时,系统会在内存中产生新的栈区,来存放这个方法的副本“这样的理解)

有没有人可以解答我的疑惑?

首先说明一下线程,线程是操作系统中的概念,线程是CPU调度的最小单位。也就是说cpu会为线程a服务一小段时间,然后被调度到线程b上服务一小段时间。cpu为线程服务,实际就是执行线程的代码。线程为了记录cpu为自己执行到了什么地方,需要有一个栈stack来进行跟踪。

在某一时刻,只有一个线程是active的,因为一般只有一个cpu。

多线程访问对象很可能会出问题,比如threadA访问一个对象,做了一半cpu就被调度到threadB了,这是这个对象的状态就是“脏”的,不完整的。如果threadB也要访问同一个对象,它接手的数据就不正确,处理结果能正确么?所以线程之间也需要“沟通”-即对对象的互斥访问,也就是线程之间的一个协议,咱们都要访问这个对象可以,但是访问之前必须要获得它的锁,否则就不能访问。

首先非常感谢你的答复。就你对线程的解释我是赞成的,但就我的理解你所说的例子只是当threadA和threadB两个线程共同访问的对象的属性也就是两个线称共享数据时才会需要互斥访问,而我第二个问题的意思是,两个线程同时调用对象的方法,而这个方法没有使用到对象的属性,并且系统会为每个调用单独开一个栈区存放被调用的方法的副本,也就不会有共享数据的情况出现,也就是被调用的方法是线程安全的。
还请各位帮忙指点一下。

线程安全一般是和你要访问的singleton对象联系在一起的的。如果该对象不是singleton的话,可以不用考虑线程安全的。
当然对于类的static变量,即使不考虑线程安全,也要注意它是所有同类型对象共享的。

我的意思就是如你所说的线程共同访问singleton对象。但这个singleton对象是没有变量,只有方法。我想知道这种情况下这个对象是否是线程安全的,如果是,那这种多线程访问一个对象的方式和线程访问对象的连接池的方式,那种效率更高,为什么?

>多线程访问一个对象的方式
>线程访问对象的连接池
这两个方式是可以互相转化的,多线程访问对象池,效率性能都会高,EJB是采用对象池这样的内部机制。

不知banq大哥的回答,是不是表示我讲的那种没有变量只有方法的singlton对象是安全的。如果是的话,我就基本上明白了。谢谢各位的回复。

另外banq大哥可不可以简单讲一下为什么访问对象池的效率要比访问单个对象要高?因为我觉得访问单个对象不用像连接池那样要建立对象和释放资源。效率反而要高点。

错了,访问对象池中的对象不需要创建对象(而创建对象需要花费比较大的时间),ejb的无态sb就是采用对象池的机理做的,效率会比较高

支持一下,这个问题也困扰我很久了。

我一直对singleton模式有一些疑问

不知道对于“使用singleton模式”与“每次创建对象”的效率

相差有多大。

这决定了我们在什么情况下可以考虑使用singleton模式

1、是这样di,一般可以把这个方法改成static的(当然没有使用static类变量的情况下)

2、你说的是对象池吧? 这是两回事来的,对象池中的对象是取出来用的,所以多线程用的还是单个单个的对象嘛。 使用对象池是可以提高效率改善质量,但多数的情况下对普通的开发人员和普通的项目是不值得di,因为还有大把大把更呆优化的地方远比这里重要。

> 支持一下,这个问题也困扰我很久了。
>
> 我一直对singleton模式有一些疑问
>
> 不知道对于“使用singleton模式”与“每次创建对象”的效?>
>
> 相差有多大。
>
> 这决定了我们在什么情况下可以考虑使用singleton模式

singleton和对象池,完全两回事,非要拉上点关系也不是不行。

还是分开来研究吧。

> 2、你说的是对象池吧?
> 这是两回事来的,对象池中的对象是取出来用的,所以多线程
> 玫幕故堑ジ龅ジ龅亩韵舐铩?> 使用对象池是可以提高效率改善质量,但多数的情况下对普通
> 目⑷嗽焙推胀ǖ南钅渴遣恢档di,因为还有大把大把更呆?> 化的地方远比这里重要。

我第二个问题的意思是,当一个不用同步的线程安全的对象被多线程同时访问时,是把这个对象做成singlton的模式还是把它放到对象池中,那个效率高,为什么。

谈到线程正好问个问题。

在jdk1.2中有一个threadLocal类,不知道大家用过没有。
以下是jdk的doc给出的注释。
This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

For example, in the class below, the private static ThreadLocal instance (serialNum) maintains a "serial number" for each thread that invokes the class's static SerialNum.get() method, which returns the current thread's serial number. (A thread's serial number is assigned the first time it invokes SerialNum.get(), and remains unchanged on subsequent calls.)

public class SerialNum {
// The next serial number to be assigned
private static int nextSerialNum = 0;

private static ThreadLocal serialNum = new ThreadLocal() {
protected synchronized Object initialValue() {
return new Integer(nextSerialNum++);
}
};

public static int get() {
return ((Integer) (serialNum.get())).intValue();
}
}

Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).

1 这样不就是意味着类中私有的static fields是线程安全的。
2 他的性能到底如何?


你可以把线程A和线程B的圆圈看成是各种操作,圆圈内部的是各种数据。其中两圆重合的部分(红色)部分是两方均需操作的公共数据,这部分数据需要同步保护。具备同步保护(这需要开发者自觉自愿的去做这件事)的红色数据可以称为线程安全的,否则就不是线程安全的。

这里有一些地方需要注意,即这里所说的线程安全其实包括了公共数据和叠加在该公共数据之上的操作这样两个要素,只谈公共数据或者该数据之上的操作是没有意义的,只要一说到线程安全,就应该把这两个要素联系在一起考虑。