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

java多线程之-----静态同步synchronized方法与synchronized(class) 代码块

2017-10-29 15:10 816 查看
这个也是我在面试中被问到的一个题目(synchronize修饰静态方法和非静态方法的区别),这个没答出来

关键字synchronized还可以应用在static静态方法上,如果这样写,那是对当前的*.java文件对应的Class类进行持锁,测试项目:类文件Service.java代码如下:

public class Service {
synchronized public static void PrintA(){
try {
System.out.println("线程的名称为:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"进入printA");
Thread.sleep(3000);
System.out.println("线程的名称为:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"离开printA");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
synchronized public static void PrintB(){

System.out.println("线程的名称为:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"进入printB");
System.out.println("线程的名称为:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"离开printB");

}
}


ThreadA的代码:

public class ThreadA extends Thread{

@Override
public void
4000
run() {
// TODO Auto-generated method stub
super.run();
Service.PrintA();
}

}


ThreadB:

public class ThreadB extends Thread{

@Override
public void run() {
// TODO Auto-generated method stub
super.run();
Service.PrintB();
}

}


运行测试代码:

public class Test1 {
public static void main(String[] args) throws InterruptedException {
ThreadA a = new ThreadA();
a.setName("A");
a.start();
ThreadB b = new ThreadB();
b.setName("B");
b.start();

}
}


运行结果:



从运行结果来看,并没有什么特别地方,都是同步的效果,和将synchronized关键字加到非静态static方法上使用的效果是一样的,其实还是有本质上的不同,synchronized关键字加到static静态方法上是给Class类上锁,而synchronized关键字加到非static静态方法上是给对象上锁:

为了验证不是同一个锁。创建新的 项目,Service.java的代码如下:

public class Service {
synchronized public static void PrintA() {
try {
System.out.println("线程的名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printA");
Thread.sleep(3000);
System.out.println("线程的名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printA");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

synchronized public static void PrintB() {
System.out.println("线程的名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");

System.out.println("线程的名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
}

synchronized public void PrintC() {
System.out.println("线程的名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程的名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");

}
}


ThreadA :

public class ThreadA extends Thread{
private Service service;
public ThreadA(Service service) {
// TODO Auto-generated constructor stub
super();
this.service = service;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
service.PrintA();
}

}


ThreadB:

public class ThreadB extends Thread{
private Service service;
public ThreadB(Service service) {
// TODO Auto-generated constructor stub
super();
this.service = service;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
service.PrintB();
}

}


ThreadC:

public class ThreadC extends Thread{
private Service service;
public ThreadC(Service service) {
// TODO Auto-generated constructor stub
super();
this.service = service;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
service.PrintC();
}

}


测试代码类:

public class Test1 {
public static void main(String[] args) throws InterruptedException {
Service service = new Service();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
ThreadC c = new ThreadC(service);
c.setName("C");
c.start();

}
}


运行结果:



结果产生异步的原因是持有不同的锁,一个是对象锁,一个是Class锁,而Class锁可以对类的所有对象实例起作用。如果不是Class锁的话,则多个实例就有多个锁,上文章有说到。下面验证Class锁对所有的实例起作用

修改运行测试文件如下:

public class Test1 {
public static void main(String[] args) throws InterruptedException {
Service service = new Service();
Service service2 = new Service();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadB b = new ThreadB(service2);
b.setName("B");
b.start();

}
}


运行结果:



由结果来看,依然是同步进行的,也就是说明了Class锁对所有实例起作用。

同步Synchronized(class) 的实质其实和synchronized static 方法一样,都是给Class加锁。验证:

修改Service代码:

public class Service {
public void PrintA() {
synchronized (Service.class) {
try {
System.out.println("线程的名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printA");
Thread.sleep(3000);
System.out.println("线程的名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printA");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

public  void PrintB() {
synchronized (Service.class) {
System.out.println("线程的名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printB");

System.out.println("线程的名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printB");
}
}
}


注意:PrintA和PrintB方法加不加static都一样了这时
再次运行代码得:




结论:静态同步synchronized方法与synchronized(class)代码块效果一样,没有本质上的区别,与非静态的方法比起来,非静态的是给对象上锁。多个对象的时候会给多个对象上锁。依旧是异步的。而静态的方法,则因为持有的是Class锁,所以多个对象创建的时候,因为其Class依旧是一样的,所有就会是同步状态
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐