目录
1.2 synchronized同时修饰method1和method2
在Java类中,有线程安全与不安全之分。线程安全的类在同一时刻,多个线程操作类方法时,需要保证只有一个线程进行操作。synchronized关键字的出现,可以保证共享资源在同一时刻被一个线程操作。
synchronized关键字在线程同步时,主要有下面三种情况:
1. 类实例对象锁;
2. 类锁;
3.对类的代码块加锁;
4. 类的重入锁
一、类实例对象锁
public class MyObject {
public synchronized void method1(){
try{
System.out.println(Thread.currentThread().getName());
Thread.sleep(4000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
public void method2(){
System.out.println(Thread.currentThread().getName());
}
}
在上面类中,使用synchronized修饰method1,method2为普通方法。在调用方式上,也有几种不同的情况
1.1 采用线程方式,用线程调用每个方法
public static void main(String[] args) {
final MyObject mo = new MyObject();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
mo.method1();
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
mo.method2();
}
},"t2");
t1.start();
t2.start();
}
结果:采用线程调用各自方法,虽然使用的同一个类实例对象,但是调用方法之间不会进行锁等待,即同时执行。
1.2 synchronized同时修饰method1和method2
结果:这种情况下,由于两个方法都进行了同步操作,当某一个线程调用一个方法时即获取了该对象的对象锁,另外一个线程调用时则会进行锁等待。
结论:在同一个实例对象下,采用不同线程调用synchronized方法和非同步方法不会产生锁等待。当两个方法同时被synchronized修饰,则共享同一个对象锁,会产生锁等待。
二、类锁
类锁,即对类进行加锁,常常使用static synchronized来修饰方法。如:
public class MyObject {
public static synchronized void method1(){
try{
System.out.println(Thread.currentThread().getName());
Thread.sleep(4000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
public synchronized void method2(){
System.out.println(Thread.currentThread().getName());
}
}
如上所示:static synchronized修饰method1, synchronized修饰method2。
结果:
(1) 通过1.1代码中不同线程调用method1和method2时,不会产生锁互斥。因为static修饰method1方法属于类方法,而method2属于实例对象方法,二者归属于不同的锁,因此不会产生锁等待。
(2) 当static synchronized同时修饰method1和method2时,方法调用会产生互斥,此时共享的是类锁。
三、类的代码块锁(略)
四、类的重入锁
synchronized的锁具有重入功能,它共享一个类实例的锁。当一个线程得到一个对象锁后,若再次请求此对象是可以再次得到该对象的锁。如:
public class SyncRepeat {
public synchronized void method1(){
System.out.println("method1..");
method2();
}
public synchronized void method2(){
System.out.println("method2..");
method3();
}
public synchronized void method3(){
System.out.println("method3..");
}
}
结果:当线程调用method1时,不存在锁等待,他们得到的都是同一个对象的锁。同时当某个类具有同步方法parent1,而子类继承该类的同时具有method2的同步方法,当method2调用parent1时,不会产生锁互斥。
五、结论
本文主要分析了synchronized关键字在对象锁与类锁方面的不同情况。对于同一个实例对象,通过线程调用同步和非同步方法,不会产生锁互斥,如果同时调用同步方法则产生互斥。对于static修饰的类锁来说,调用static synchronized方法和synchronized方法时,由于方法二者的锁归属不同,不会产生锁等待。