Java 中synchronize函数的实例详解

java中的一个类的成员函数若用synchronized来修饰,则对应同一个对象,多个线程像调用这个对象的这个同步函数时必须等到上一个线程调用完才能由下一个线程调用。

那么如果一个类同时有两个成员函数是由synchronized修饰如代码所示,对与同一个对象,是否可以在两个线程运行时,一个调用funcA,同时另一个调用funcB?

Mysyn是这样一个类,如果我有两个线程,一个在run方法中先运行funcA再运行funcB,另一个线程在run方法中先运行funcB再运行funcA。那有没有可能出现这样的情况:在输出时start A...后面直接输出start B...?

public class MySyn {
public synchronized void funcA(String str){
System.out.println(str+":");
System.out.println("start A...");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("...A end");
}
public synchronized void funcB(String str){
System.out.println(str+":");
System.out.println("start B...");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("...B end");
}
}
测试代码如下:
这个线程是先运行funcA的
public class Mythread implements Runnable {
private MySyn mysyn;
private String id;
public Mythread(MySyn syn, String id){
this.mysyn = syn;
this.id = id;
}
@Override
public void run() {
this.mysyn.funcA(id);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.mysyn.funcB(id);
}
public static void main(String arg[]){
MySyn syn=new MySyn();
Thread t1 = new Thread(new Mythread(syn, "t1"));
Thread t2 = new Thread(new YourThread(syn, "t2"));
t1.start();
t2.start();
}
}

这个线程是先运行funcB的

public class YourThread implements Runnable {
private MySyn mysyn;
private String id;
public YourThread(MySyn syn, String id){
this.mysyn = syn;
this.id=id;
}
@Override
public void run() {
this.mysyn.funcB(id);
this.mysyn.funcA(id);
}
}

输出结果多是:

t1:

start A...

...A end

t2:

start B...

...B end

t2:

start A...

...A end

t1:

start B...

...B end

如果取消Mythread的run方法中两个函数调用间的sleep,那结果多是:

t1:

start A...

...A end

t1:

start B...

...B end

t2:

start B...

...B end

t2:

start A...

...A end

个人结果可能因线程调度不同,但是永远不会有:start A...后面直接输出start B...

那如果funcB不是一个同步函数,那上述代码运行结果会是怎么样呢?

代码稍加改动,把funcB的synchronized关键字去掉。运行结果为:

t2:

t1:

start A...

start B...

...A end

t1:

start B...

...B end

t2:

start A...

...B end

...A end

显然出现了start A...后面直接输出start B...的结果。

同样如果Mysyn类如果有一个public 的成员变量,多线程也可以再同步函数被调用的同时,由另一个线程修改这个成员变量。

上述实验说明了:同步的成员函数只能在同一个对象的同步函数调用中对其他同步函数(包括本身)有排它的效果,即多线程运行中,同一个对象当前只能有一个同步函数在运行,但不排除其他非同步函数的运行或对成员进行访问。

那现在假设某个类有两个静态同步方法,那情况怎么样呢?

具体实现,我就不重复了,因为结果类似:

在多线程中,同一个类,当前只能有一个类同步函数(静态同步函数)在运行,但不排除其他非同步静态函数的运行或对静态成员的访问