synchronized关键字的使用

1.synchronized修饰非静态方法

public class MyObject {

    synchronized public void method1(){
        System.out.println("method1");
        method2();
    }

    synchronized public void method2(){
        System.out.println("method2");
    }

    public void method3(){
        System.out.println("method3");
    }
}

synchronized放在public之前或者之后没有区别。
首先实例化MyObject类:MyObject myObject = new MyObject();
1、修饰某个类中的非静态方法时,synchronized锁的并不是所修饰的方法,而是当前类的对象。也就是锁的是实例化的对象: myObject
2、当线程A获得myObject 对象的锁之后正在调用myObject.method1()方法,这时线程B想要调用myObject.method2()方法则需要等待,也就是同步。结论:A线程先持有myObject 对象的锁,线程B如果这时想调用myObject 对象中的任意一个synchronized类型方法都需要等待,也就是同步。
3、新实例化一个对象:MyObject myObject2 = new MyObject();这时候线程A调用myObject.method1()方法,线程B调用myObject2.method1()方法,这时是异步的,因为分别是两把不同锁。
4、线程A先持有myObject 对象的锁,线程B可以异步调用myObject对象中没被synchronized修饰的方法。如:
线程A调用myObject.method1();线程B调用myObject.method3();这时执行结果是异步的。
5、synchronized拥有锁重入功能,也就是当线程A调用myObject.method1()方法,myObject.method1()调用本类中的其他synchronized方法/块时,是永远可以得到锁的。锁重入也支持父子类继承的情况:子类可以通过锁重入调用父类的同步方法。
6、子类重写了父类的同步方法,如果子类中重写的方法不使用synchronized关键字,那么该方法就变成了非同步方法,加上synchronized关键字后就变成了同步方法。

2.synchronized(this)代码块

public class MyObject {

    public void method1(){
        System.out.println("method1异步执行!");
        synchronized (this){
            System.out.println("method1");
        }
    }

    public void method2(){
        System.out.println("method2异步执行!");
        synchronized (this){
            System.out.println("method2");
        }
    }

    public void method3(){
        System.out.println("method3");
    }
}

首先实例化MyObject类:MyObject myObject = new MyObject();
1、和synchronized方法一样synchronized(this)代码块也是以当前实例对象作为锁,因此A线程先持有myObject 对象的锁,线程B如果这时想调用myObject 对象中的任意一个synchronized(this)代码块都需要等待,也就是同步。
2、synchronized(this)的优点:可以只同步需要同步的部分代码,没在同步代码块中的代码可以异步执行,这相对synchronized方法来说增加了执行效率。如:线程A和线程B都调用myObject.method1()方法,这时synchronized (this)代码块上面的那行输出代码是异步的。

3.synchronized(非this对象)代码块

public class MyObject {

    public void method1(){
        String s = new String();
        synchronized (s){
            System.out.println("method1");
        }
    }

    public void method2(){
        System.out.println("method2异步执行!");
        synchronized (this){
            System.out.println("method2");
        }
    }

    synchronized public void method3(){
        System.out.println("method3");
    }
}

首先实例化MyObject类:MyObject myObject = new MyObject();
1、synchronized(非this对象)代码块写法是将括号中的“非this对象”加锁。
2、synchronized(非this对象)代码块优点:synchronized(非this对象)代码块和当前对象中其他同步方法是异步的,因为是两把不同的锁,不与其他锁this同步方法争抢this锁,可以提升运行效率。如:线程A调用myObject.method1()方法,线程B调用myObject.method2()myObject.method3()方法,这时是异步的,因为分别是两把不同的锁。
3.如:

class MyObject2 {
    public void method1(MyObject3 myObject3){
        synchronized (myObject3){
            System.out.println("method1");
        }
    }
}
class MyObject3 {
    synchronized public void method1(){
        System.out.println("method1");
    }
}
class MyThread2 extends Thread{
    private MyObject2 myObject2;
    private MyObject3 myThread3;
    public MyThread2(MyObject2 myThread2,MyObject3 myThread3){
        this.myObject2 = myThread2;
        this.myThread3 = myThread3;
    }
    @Override
    public void run() {
        myObject2.method1(myThread3);
    }
}
class MyThread3 extends Thread{
    private MyObject3 myThread3;
    public MyThread3(MyObject3 myThread3){
        this.myThread3 = myThread3;
    }
    @Override
    public void run() {
        myThread3.method1();
    }
}

class test{
    public static void main(String[] args) throws InterruptedException {
        MyObject2 myObject2 = new MyObject2();
        MyObject3 myObject3 = new MyObject3();
        MyThread2 myThread2 = new MyThread2(myObject2,myObject3);
        MyThread3 myThread3 = new MyThread3(myObject3);
        myThread2.start();
        myThread3.start();
    }
}

这时两线程执行是同步的,因为使用的同一把锁。代码示例中是synchronized方法,synchronized(this)代码块和synchronized同理。

4.静态synchronized方法与synchronized(class)代码块

class Service{
    synchronized public static void method1(){
        System.out.println("静态方法上加锁");
    }

    public static void method2(){
        synchronized (Service.class){
            System.out.println("synchronized(class)代码块");
        }
    }
}

1、*.java对应的class类对象是单例的,在static方法上使用synchronized关键字时,是当前静态方法所在的类对应的class类的单例对象作为锁。class锁对所有对象实例起作用,也就是所有实例对象是同一把锁。而非static方法上使用synchronized关键字是其所对应的单个实例作为锁,多个实例对象的时候就是多把不同的锁了。
2、synchronized(class)代码块和synchronized static方法同理。

参考书籍:Java多线程编程核心技术(第2版)高洪岩 著

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值