Java中静态方法是否属于线程安全

姓骚扰 发布于 2012/07/10 22:12
阅读 13K+
收藏 1

对Java中的静态修饰符还是不太了解.如果定义个静态方法,方法内部不涉及调用外部变量,比如说这个方法是为了解决某个问题的一个工具方法,就像"Array.getLong(arg0, arg1)"这种一样,那么这个静态方法在遇到多线程问题的时候是否会存在安全隐患呢? 我写了下面一段代码,用两个线程不停的去调用类中的一个静态方法,试问:Sytem.err.println()中的内容是否会打印出来?

我执行了很长时间也没见打印出来,对于概念也模糊不清,所以依然无法做出判断,求帮忙解决下我的疑惑。

public class Test implements Runnable {

	public static void main(String[] args) {
		new Thread(new Test(), "Thread 1").start();
		new Thread(new Test(), "Thread 2").start();

	}

	public static void show() {
		int a = 0;
		if (a != 0)
			System.err.println("未处理前:" + a);
		a++;
	}

	@Override
	public void run() {
		while (true) {
			show();
		}
	}

}

Java中静态方法是否属于线程安全
加载中
0
姓骚扰
姓骚扰

搞清楚这个问题的关键在于,静态方法中定义的内部变量是否属于类或类实例共享级别?  如果是,那么这个就肯定会打印出a的值,并且也能说明静态方法不属于多线程安全?    这是是最大的疑惑。。。

求解释。。。

0
chunquedong
chunquedong
每个方法都有自己独立的栈空间,把a放到外面试试
姓骚扰
姓骚扰
那么静态方法在Java到底具有什么作用呢? 可以被类直接调用,可以直接使用静态变量。其他的我真不知道还有什么作用了?
chunquedong
chunquedong
回复 @韩克 : 静态方法共享,但每个方法内部的局部变量是私有的,每调用一次方法,会在栈中分配局部变量,方法退出时释放所有局部变量空间。所以方法递归调用的时候,不会相互影响。如果还不清楚查一下C语言函数的递归和调用。
姓骚扰
姓骚扰
静态方法不是和静态变量一样吗?和类一起被装载,并且在类和类的实例之间共享? 你说的每个方法都有自己的独立的栈空间,这个是什么意思?能帮忙解释下吗?
0
柴俊堃
就这段代码而言,确实是安全的,但是static方法不一定是线程安全的。和普通方法一样,一旦你传入的内容是共享的引用类型,即便是static方法,也一样不是线程安全的。
姓骚扰
姓骚扰
搞清楚这个问题的关键在于,静态方法中定义的内部变量是否属于类或类实例共享级别? 如果是,那么这个就肯定会打印出a的值,并且也能说明静态方法不属于多线程安全。
0
柴俊堃
这段代码你可以用C语言的想法去想。进入一个函数,会保存现场。把状态压入堆栈,然后申请了4字节寄存器,然后一直都是对这个寄存器进行操作。每次执行方法都要保存现场,重新来过,那么当然是线程安全的,但是还是我上面说的,静态方法不见得是线程安全的,你的输入也有影响
0
fdhay
fdhay

首先要搞清楚变量的作用域和线程安全的数据是针对哪个作用域的变量而言。

1:上面的代码,说的是方法内的局部变量。每个线程在启动以后,都有自己的栈区,这个内存区域会保存对应线程在运行期间进行方法调用的方法变量和方法内的局部变量。所以从这份分析来看,方法内部变量始终只存在于他所在的线程,也就不会有线程安全方面的问题。当然,如果是引用类型的对象,由于对象本身不在每个线程的栈区,而是在java堆中,所以就要考虑临界资源的多线程访问问题。

2:线程安全是针对多个线程能在运行期间共同访问到的临界资源的访问而言的。如第一点所说,这样的临界资源是指在线程自己的栈区外的资源,比如类实例的成员变量,类实例本身。。

 

fdhay
fdhay
计算机中,操作数和操作指令是不同的概念。临界资源只针对操作数才有意义。而操作指令只是 计算机线程的执行序列,哪个线程都可以执行,都可以同时执行,这个跟 线程安全(只针对操作数才有意义)毫无关系。我已经说到,方法内的局部变量,已经是放在每个线程自己的栈区,这个局部变量作为操作数,就只能被他自己的线程访问到。
姓骚扰
姓骚扰
现在。静态方法和静态成员变量一样,都是属于类和实例共享的,这会搞不清楚的就是静态方法中定义的变量到底是属于类共享级的还是非共享的?
0
Andre.Z
Andre.Z

线程安全和static没啥关系。
自家的馍馍没人会抢,外面的香饽饽才吃香。

姓骚扰
姓骚扰
求说明哈。
0
特劳特
特劳特
简单总结就一句话,有状态的对象是线程不安全,无状态的就是安全的
0
特劳特
特劳特
a属于局部变量,对对象来说无状态,肯定是线程安全的
0
Jeky
Jeky

不涉及共享变量(全局/静态)永远线程安全

0
b
buptwhis
你这个静态方法本身并没有与其它线程共享资源,它用到的只是它自身的资源,线程是否安全只需要关注它用到的资源是否可能在其它线程中共用。
返回顶部
顶部