JAVA 静态块 线程问题

Python016

JAVA 静态块 线程问题,第1张

想了很久,终于弄明白为什么了。

静态块确实是在main之前运行,但这不是关键。 关键在于类的初始化过程。

类的初始化,包括静态赋值如 static boolean initialized = false和静态初始化块, static { ... }, 按照声明的顺序依次执行。某个线程在对某个类进行初始化的时候,会先给这个类加锁,直到初始化全部完成之后才释放锁。 你的代码存在死锁问题。

把代码改成这样,看看输出是什么:

public class HelloWorld {

private static boolean initialized = false

static Thread t = new Thread(new Runnable() {

public void run() {

System.out.println("aaaa")

System.out.println(initialized)// label

System.out.println("Hello ")

initialized = true

}

})

static {

t.start()

}

static {

try {

Thread.sleep(500)

}

catch(Exception e) {

}

System.out.println("bbbb")

}

public static void main(String[] args) {

System.out.println(" world!")

}

}

你会发现输出是这样的:

aaaa

bbbb

false ....

注意,bbbb总是在false之前打印,不管sleep多长时间。

而在run方法里,打印aaaa之后应该紧接着打印false才对,为什么还要等待睡觉中的bbbb呢?

虚拟机在执行 main之前,先要加载HelloWorld类,那么mian线程会对HelloWorld的Class加锁,然后依次执行

static boolean initialized = false

static Thread t = ...

static { t.start()}

static { sleep(500)print "bbbb"}

执行完这些语句,才会把锁释放。

在这之间,启动了t线程,t先打印aaaa,然后试图打印initialized,但是这时候HelloWorld的Class被锁定了,所以t线程必须等待main线程把锁释放掉,也就是上面所有的static语句执行完毕。等main线程执行完了bbbb,就会把锁释放掉,然后t线程就可以继续执行了。

如果加入了join语句,那么main线程就会等待t线程,但是t线程试图访问initialized的时候必须等待main线程,这就导致了死锁。你把label语句去掉之后,就不需要等到main线程了,所以会把hello打印出来。

总的结论:java是线程安全的,即对任何方法(包括静态方法)都可以不考虑线程冲突,但有一个前提,就是不能存在全局变量。如果存在全局变量,则需要使用同步机制。\x0d\x0a\x0d\x0a如下通过一组对比例子从头讲解:\x0d\x0a 在多线程中使用静态方法会发生什么事?也就是说多线程访问同一个类的static静态方法会发生什么事?是否会发生线程安全问题?\x0d\x0apublic class Test {\x0d\x0apublic static void operation(){\x0d\x0a// ... do something\x0d\x0a}\x0d\x0a}\x0d\x0a 事实证明只要在静态函数中没有处理多线程共享数据,就不存在着多线程访问同一个静态方法会出现资源冲突的问题。下面看一个例子:\x0d\x0apublic class StaticThread implements Runnable {\x0d\x0a@Override\x0d\x0apublic void run() {\x0d\x0a// TODO Auto-generated method stub\x0d\x0aStaticAction.print()\x0d\x0a}\x0d\x0apublic static void main(String[] args) {\x0d\x0afor (int i = 0i 回答于 2022-12-11