Java-Synchronized(二)-对象锁与类锁

两种用法

对象锁

包括方法锁(默认锁对象为this当前对象实例)和同步代码块锁(自己指定锁对象)

类锁

指synchronized修饰的静态方法或指定锁为Class对象

对象锁-方法锁
public class SynchronizedObjectMethod3 implements Runnable {

    static  SynchronizedObjectMethod3 instance = new SynchronizedObjectMethod3();

    public static void main(String[] args) {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
//        t1.join();
//        t2.join();
        while(t1.isAlive() || t2.isAlive()) {}
        System.out.println("finished");
    }

    @Override
    public void run() {
        method();
    }

    public synchronized void method() {
        System.out.println("I'm object method lock " + Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("I'm object method lock " + Thread.currentThread().getName() + " is over");
    }
}
对象锁-代码块

我们可以使用this来加锁,但可能一个类中不止一个代码段需要用到锁,我们希望它们是独立的,所有我们需要自己去定义一个对象,这个对象的作用就是充当锁的作用,它再无其它的任何含义(信号量机制里面的最简单的0/1互斥)

public class SynchronizedObjectCodeBlock2 implements Runnable {

    static  SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2();

    public static void main(String[] args)  throws InterruptedException{
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
//        t1.join();
//        t2.join();
        while(t1.isAlive() || t2.isAlive()) {}
        System.out.println("finished");
    }

    @Override
    public void run() {
        synchronized (this) {
            System.out.println("I'm object code block " + Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("I'm object code block " + Thread.currentThread().getName() + " is over");
        }
    }
}
public class SynchronizedObjectCodeBlock2 implements Runnable {

    static  SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2();

    private final Object lock1 = new Object();
    private final Object lock2 = new Object();

    public static void main(String[] args)  throws InterruptedException{
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
//        t1.join();
//        t2.join();
        while(t1.isAlive() || t2.isAlive()) {}
        System.out.println("finished");
    }

    @Override
    public void run() {
        synchronized (lock1) {
            System.out.println("I'm object code block lock1 " + Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("I'm object code block lock1 " + Thread.currentThread().getName() + " is over");
        }

        synchronized (lock2) {
            System.out.println("I'm object code block lock2 " + Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("I'm object code block lock2 " + Thread.currentThread().getName() + " is over");
        }
    }
}

再随着业务逻辑的复杂,手工用synchronized去实现并发也是有风险的,这种时候我们一般会使用框架。

类锁的概念

概念

只有一个类对象,Java类可能有很多对象,但只有一个Class对象(反射机制里面的类类型)

本质

所谓类锁:不过是Class对象的锁而已

它具有两种形式:

  1. synchronized加在static方法上
  2. synchronized(*.class)代码块

用法和效果

类锁只能在同一时刻被一个对象拥有(不同的Runnable实例只有一个类锁,这个之前的对象锁是不同的)

类锁-静态方法锁

其实静态方法锁相比于普通方法锁,多了一个static,static关键字在Java中本身就有“全局”的含义,它实现不同实例间同步也不难理解

public class SynchronizedStaticMethod4 implements Runnable {

    static  SynchronizedStaticMethod4 instance1 = new SynchronizedStaticMethod4();
    static  SynchronizedStaticMethod4 instance2 = new SynchronizedStaticMethod4();

    public static void main(String[] args) {
        Thread t1 = new Thread(instance1);
        Thread t2 = new Thread(instance2);
        t1.start();
        t2.start();
//        t1.join();
//        t2.join();
        while(t1.isAlive() || t2.isAlive()) {}
        System.out.println("finished");
    }

    @Override
    public void run() {
        method();
    }

    public static synchronized void method() {
        System.out.println("I'm object method lock " + Thread.currentThread().getName());
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("I'm object method lock " + Thread.currentThread().getName() + " is over");
    }
}

代码对比对象锁-普通方法锁变化也就是两个Runnable实例,加锁的方法被static修饰。

类锁-*.class代码块

如果学习过Java的反射机制的话就会知道.class获取到的该类的类类型,这对于一个类创建的实例而言自然只有一个类类型,在类的层面来加锁也就实现了。

public class SynchronizedClassClass5 implements Runnable{

    static  SynchronizedClassClass5 instance1 = new SynchronizedClassClass5();
    static  SynchronizedClassClass5 instance2 = new SynchronizedClassClass5();

    public static void main(String[] args) {
        Thread t1 = new Thread(instance1);
        Thread t2 = new Thread(instance2);
        t1.start();
        t2.start();
//        t1.join();
//        t2.join();
        while(t1.isAlive() || t2.isAlive()) {}
        System.out.println("finished");
    }

    @Override
    public void run() {
        method();
    }

    public static synchronized void method() {
    // 三种获取类类型的方式都是可以的
//        synchronized (SynchronizedClassClass5.class) {
//        synchronized (instance1.getClass()) {
        Class c = null;
        try {
            c = Class.forName("com.nevercome.concurrency.SynchronizedClassClass5");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        synchronized (c) {
            System.out.println("I'm object method lock " + Thread.currentThread().getName());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("I'm object method lock " + Thread.currentThread().getName() + " is over");
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值