synchronized 锁其实就是一个对象锁,我们用具体的例子来看看它到底是怎么运行的:
测试一:
//同步锁失效,测试1
public class Syn1 {
public synchronized void start(){
System.out.println("仰卧");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("起坐");
}
}
//同步锁失效,测试1(每次都会new一个对象)
public class RunSyn1 extends Thread{
public RunSyn1(){
}
@Override
public void run(){
Syn1 mSyn=new Syn1();
mSyn.start();
}
}
//调用测试
new Runnable() {
@Override
public void run() {
for(int i=0;i<3;i++){
RunSyn1 runSyn=new RunSyn1(); //在此更换方法
runSyn.start();
}
}
}.run();
如果是 仰卧——>起坐说明同步锁synchronized成功执行 ,我们看一下结果:
结果是仰卧 仰卧 仰卧 起坐 起坐 起坐,说明synchronized没有成功锁住,因为程序每次都new了一个对象,并不是对同一个对象操作,我们试着调整一下代码:
测试二:
//同步锁有效,测试2
public class Syn2 {
public synchronized void start(){
System.out.println("仰卧");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("起坐");
}
}
//同步锁有效,测试2(操作同一个对象)
public class RunSyn2 extends Thread{
private Syn2 mSyn2;
public RunSyn2(Syn2 syn2){
mSyn2=syn2;
}
@Override
public void run(){
mSyn2.start();
}
}
final Syn2 mSyn2=new Syn2();//执行方法二需要有参构造函数
new Runnable() {
@Override
public void run() {
for(int i=0;i<3;i++){
RunSyn2 runSyn=new RunSyn2(mSyn2); //在此更换方法
runSyn.start();
}
}
}.run();
结果:
很明显, synchronized对同一个对象的同步锁成功执行。但是如果是多个对象创建,线程同步又得怎么处理呢?
测试三:
//多个对象创建,线程同步有效(重要的是锁住这个类,加static是一样的效果)
public class Syn3 {
public synchronized static void start(){
System.out.println("仰卧");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("起坐");
}
}
//多个对象创建,线程同步有效
public class RunSyn3 extends Thread{
public RunSyn3(){
}
@Override
public void run(){
Syn3 mSyn=new Syn3();
mSyn.start();
}
}
new Runnable() {
@Override
public void run() {
for(int i=0;i<3;i++){
RunSyn3 runSyn=new RunSyn3(); //在此更换方法
runSyn.start();
}
}
}.run();
结果:
其实只是在Syn里面只加个静态方法,可见同步静态方法相当于同步Syn 这个类。也可以这样写:
public static void start(){
synchronized(Syn.class){
......
}
}
总结:
1、非静态方法的同步锁只对同一个对象有效。对不同对象起不到同步的作用。
2、静态方法同步锁锁的是类,锁是整个类对象的锁,这个对象是就是这个类(X.class)。
3、关于锁的范围,能锁住代码块的范围就就尽量不要锁方法。比较加锁之后,要等待其他线程执行完,相对比较耗时。
具体例子请到这里下载 synchronized测试案例