2010-04-16 121 views
4

考虑这个类,没有实例变量,只有非同步的方法可以从这个信息推断出这个类在线程安全?这个类是否线程安全?

public class test{ 

public void test1{ 

// do something 

} 

public void test2{ 

// do something 


} 

public void test3{ 

// do something 

} 



} 
+3

您需要方法参数。 – 2010-04-16 14:01:00

+0

但如果所有的函数都是线程安全的,有些人可能会说这个类是线程安全的...... – 2010-04-16 14:01:12

回答

3

不是线程安全意味着如果多个线程同时尝试访问该对象,则某个访问可能会发生改变,并导致问题。考虑以下内容:

int incrementCount() { 
    this.count++; 
    // ... Do some other stuff 
    return this.count; 
} 

不会是线程安全的。为什么不是?设想线程1访问它,增加count,然后进行一些处理。在通过函数时,另一个线程访问它,再次增加count。第一个线程,从1到2,现在从1到3返回。线程2会看到它也从1到3,所以2发生了什么?

在这种情况下,你会想是这样的(记住,这不是任何特定语言的代码,但最接近的Java,只有2一个我做线程中)

int incrementCount() synchronized { 
    this.count++; 
    // ... Do some other stuff 
    return this.count; 
} 

这里的​​关键字可以确保只要有一个线程正在访问它,就不会有其他线程可以访问它。这意味着线程1击中它,count从1到2,如预期。线程2在1处理时击中它,它必须等到线程1完成。完成后,线程1得到2的返回,然后线程2进入throguh,并得到预期的3.现在,一个例子,类似于你在那里,这将是完全线程安全的,不管什么:

int incrementCount(int count) { 
    count++; 
    // ... Do some other stuff 
    return this.count; 
} 

为这里碰了唯一的变量是完全本地的功能,不存在情况下两个线程同时访问它可以尝试从其他改变数据的工作。这将使它线程安全。

因此,为了回答这个问题,假设函数不修改特定调用函数之外的任何内容,那么是的,该类可以被认为是线程安全的。

0

是的,只要没有实例变量。只使用输入参数和局部变量的方法调用本质上是线程安全的。你可能会考虑使这些方法也是静态的,以反映这一点。

0

如果它没有可变状态 - 它是线程安全的。如果你没有任何国家 - 你是通过联系线程安全的。

+1

不幸的是,它并不是那么简单 - 请参阅其他答案。 – 2010-04-16 14:03:50

6

它完全取决于方法变异的状态。如果它们没有共享状态,它们是线程安全的。如果它们只改变本地状态,它们是线程安全的。如果他们只调用线程安全的方法,则它们是线程安全的。

+0

你可以扩展它来访问'ThreadLocal'实例。它们是存在的状态不仅仅是调用范围而是没有线程危险的好方法。 – 2010-04-16 14:14:05

1

取决于这些方法内发生了什么。如果他们操纵/调用任何不是线程安全的方法参数或全局变量/单例,则该类也不是线程安全的。

(是的,我看到如下所示的方法,在这里有没有参数,但没有括号要么,所以这显然是不完整的工作代码 - 它甚至不作为编译的。)

0

不,我不这么认为。

例如,其中一种方法可以从另一个类获得一个(非线程安全)单例对象并对该对象进行变异。

2

考虑从约线程安全的文章下面的引号(“Java理论与实践:表征线程安全”):

在现实中,线程安全的任何定义都将有一定程度的圆,因为它必须吸引班级的规范 - 这是一个非正式的,散文描述什么类别,它的副作用,哪些国家有效或无效,不变量,先决条件,后置条件等等。 (由规范施加的对象状态的约束仅适用于外部可见状态 - 可以通过调用其公共方法并访问其公共方法来观察 - 而不是其内部状态,而内部状态实际上代表了其状态私人领域。)

线程安全

对于一类是线程安全的,它首先必须正确运行在单线程环境。如果一个类被正确地实现了,这是另一种说明它符合它的规范的方式,那么在该类的对象上没有任何操作序列(读写公共字段和调用公共方法)应该能够将对象无效状态,观察对象处于无效状态,或违反任何类的不变量,前置条件或后置条件。

此外,为了使类成为线程安全的,从上面描述的意义上讲,当从多个线程访问时,无论通过运行时环境执行这些线程的调度或交错如何,它都必须继续正确地行为,而在调用代码部分没有任何额外的同步。其效果是线程安全对象上的操作对所有线程都将以固定的,全局一致的顺序出现。

所以你的类本身是线程安全的,只要它没有任何副作用。只要方法改变任何外部对象(例如,一些单身人士,正如其他人已经提到的那样),它不再是线程安全的。

0

是的 - 这个类是线程安全的,但这并不意味着你的应用程序是。

如果应用程序中的线程无法并发访问堆状态,则该线程安全。 Java中的所有对象(以及它们的所有字段)都是在堆上创建的。所以,如果对象中没有字段,那么它是线程安全的。

在任何实际应用中,对象都会有状态。如果你可以保证这些对象不被同时访问,那么你有一个线程安全的应用程序。

有一些方法可以优化对共享状态的访问,例如原子变量或使用volatile关键字,但我认为这超出了你的要求。

我希望这会有所帮助。