synchronized的介绍

我对synchronized关键字算是很熟悉的了,但是有些时候一些概念还是没有搞明白,今天通过对wiki翻译以及博客的学习,从概念和类别上对其进行区分,并整理了一套自己的理解方式。

从类别来区分

从类别上可以将锁分为类级别锁对象级别锁
1. 类级别锁,作用于整个类的的同步锁,例如Object.class
2. 对象级别锁,new Object()产生的锁,不同的实例所持有的锁是不同的。
3. this锁,也属于对象级别的锁。不同的实例所持有的锁是不同的。

类级别锁和对象级别锁的区别

  • 类级别锁是针对类的,无论创建多少实例对象,他们都拥有同一个类级别的锁。
  • 对象级别锁,针对实例对象。伴随着new对象,会有不同的锁对象。不同的锁没有互斥性。
    下面看一段代码:
    使用代码块来说明两者的区别,更加直观一些
    synchronized (blockerLock){}代表对象级别的锁,
    synchronized (SyncThread.class){}代表类级别锁
static class SyncThread extends Thread{
    //这里写成非静态的,随着SyncThread的创建,同时生成不同的blockerLock对象
        private Object blockerLock = new Object();
        public SyncThread(){

        }
        @Override
        public void run() {
            synchronized (blockerLock){
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " 当前等待的线程object " + blockerLock);
                synchronized (SyncThread.class){
                    System.out.println(Thread.currentThread().getName() + " 当前等待的线程 " + SyncThread.class);
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " 当前锁 SyncThread.class= " + SyncThread.class);
                }
                System.out.println(Thread.currentThread().getName() + "over = ");
            }
        }
    }
代码调用部分分析

随着new SyncThread()的创建,同时也创建多个blockerLock对象,在synchronized (blockerLock)时,对象锁不同,因此不会互斥。打印的对象值是随机的
而进入synchronized (SyncThread.class)时,都持有类锁,所以会进入互斥状态,每个线程会等待锁的释放。所以打印的对象是一致的。

public static void main(String[] args) {
        syncThreadTest();
    }
    public static void syncThreadTest(){
        for (int i=0; i < 10; i++){
            SyncThread syncThread = new SyncThread();
            syncThread.start();
        }
    }

synchronized的修饰范围

  1. 修饰方法
    相当于对象级别锁(this)
public synchronized void method(String name,String description)
  1. 修饰静态方法
    相当于类级别锁
public synchronized static void staticMethod(String name,String description)
  1. 同步代码块
    可以根据需求添加不同的对象级别锁或者类级别锁
public void methodToBlock(){
        synchronized (SyncObject.class){
            System.out.println("synchronized Block method SyncObject.class");
            synchronized (this){
                System.out.println("synchronized Block method this");
            }
        }
        System.out.println("非锁代码块的输出...");
    }

死锁

  • 一开始,线程A持有锁Lock1,线程B持有锁Lock2。
  • 当线程A去执行toWc()时,需要持有锁Lock2,并释放Lock1,但是Lock2的锁正在被线程B所持有,因此线程A在等待状态;
  • 线程B也去执行toWc()时,需要持有Lock1,并释放Lock2,但是Lock1被线程A所持有,因此线程B也处于等待状态。
public class DeadLock {
    private String did;
    public DeadLock(String did){
        this.did = did;
    }
    public synchronized void eat(DeadLock deadLock){
        System.out.println(this.toString() + " 当前对象 " + Thread.currentThread().getName() + " 排队吃饭");
        try {
            Thread.sleep(1000);
            System.out.println(this.toString() + " 当前对象 " + Thread.currentThread().getName() + " 模拟吃饭过程....");
            deadLock.toWc();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void toWc(){
        System.out.println(this.toString() + " 当前对象 " + Thread.currentThread().getName() + " 排队上厕所");
        try {
            Thread.sleep(1000);
            System.out.println(this.toString() + " 当前对象 " + Thread.currentThread().getName() + " 模拟上厕所过程....");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String toString() {
        return did;
    }

    public static void main(String[] args) {
        final DeadLock deadLock1 = new DeadLock("LockA");
        final DeadLock deadLock2 = new DeadLock("LockB");

        Runnable runnableA = new Runnable() {
            public void run() {
                deadLock1.eat(deadLock2);
            }
        };

        Thread t1 = new Thread(runnableA, "runA");
        t1.start();

        Runnable runnableB = new Runnable() {
            public void run() {
                deadLock2.eat(deadLock1);
            }
        };

        Thread t2 = new Thread(runnableB, "runB");
        t2.start();
    }
}

可重入内置锁

可重入性的体现

public synchronized void methodA(){
    this.methodB();
}
public synchronized void methodB(){
}
  • synchronized是一个可重入锁

你可能感兴趣的:(java基础,java多线程学习,多线程,synchronized)