您的位置:首页 > 编程语言 > Java开发

JAVA多线程安全之构造函数

2017-08-28 18:00 519 查看
在一般情况下,Java的构造函数总结如下:

在构造函数一开始,this就是可用的了。 
构造函数和普通函数一样,并不是默认被synchronized 的,有可能出现同步问题。 
如果构造函数中访问静态变量的话,必须同步这个静态变量,否则一定会出问题。 
如果只访问成员变量的话,无论在任何线程中,每一次构造函数被调用,其中的成员变量都是新建造出来的,因此不可能出现说在这个线程中运行的构造函数 会访问到另一个线程中运行的构造函数中的成员变量的情况,因此这就是我所说的“访问成员变量不可能出现同步问题”的意思。 这里的前提是,两个线程中都运行的是构造函数,而不是其他方法(例如start所启动的run方法。)。 
如果在构造函数中,把this交给其他的线程去访问,则其他线程可能在this实例还未初始化完毕时就访问了其中的变量,这有可能产生同步问题。这时需要显式同步this对象。

构造方法不需要同步化,因为它只可能发生在一个线程里,在构造方法返回值前没有其他线程可以使用该对象。(一个线程已经在构造方法里面了,另外一个线程也可以调用构造方法,第一个线程里面生成的对象和第二个线程里面生成的对象是不同的对象。)

 

构造方法里面使用的静态属性,是需要同步的,构造方法不执行完成其他线程是没有办法访问该对象的,但是类对象是已经存在的,可以被多个线程访问:如
public class Test {
public static int id=0;
public int c;
public Test() {
c=id;
System.out.println(Thread.currentThread().getName() + "到达");
try{
Thread.sleep(100);
}catch(InterruptedException e){
e.printStackTrace();
}
id++;
}
public static void main(String [] args){
class ThreadTst extends Thread {
public void run(){
Test test=new Test();
System.out.println(test.c);
}
}
new ThreadTst().start();
new ThreadTst().start();
}
}/* output
Thread-0到达
Thread-1到达
0
0
*/
public class Test {
public static int id=0;
public int c;
public Test() {
synchronized(Test.class) {
c=id;
System.out.println(Thread.currentThread().getName() + "到达");
try{
Thread.sleep(100);
}catch(InterruptedException e){
e.printStackTrace();
}
id++;
}
}
public static void main(String [] args){
class ThreadTst extends Thread {
public void run(){
Test test=new Test();
System.out.println(test.c);
}
}
new ThreadTst().start();
new ThreadTst().start();
}
}
/* output
Thread-0到达
0
Thread-1到达
1
*/


子类可以置换掉父类的同步方法,使它同步或不同步。这就是说,子类的方法不继承其父类方法的特性。父类的方法不改变,如果明显地调用父类的同步方法,那么这个将是同步调用的。

 

如果在构造函数中,把this交给其他的线程去访问,则其他线程可能在this实例还未初始化完毕时就访问了其中的变量,这有可能产生同步问题。这时需要显式同步this对象。

class A {
int i;

public A () {
synchronized(this) {
new Snippet(this);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
i = 2;
}
}
}

public class Snippet extends Thread {
A a;

public Snippet(A a) {
this.a = a;
start();
}

public void run() {
synchronized(a) {
System.out.println(a.i);
}
}

public static void main(String[] args) {
new A();
}
}
/* Output:
2
*///:~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: