Synchronized关键字的使用

1、修饰静态方法

public class SynchronizedDemo {
    public static int i=0;
    public synchronized static void accessResource() {
        try {
            i++;
            TimeUnit.SECONDS.sleep(2);
            System.out.println(Thread.currentThread().getName()+"is running:" + i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        for (int i=0;i<5;i++){
            new Thread(SynchronizedDemo::accessResource).start();
        }
    }
}

 2.修饰非静态方法:

public class SynchronizedDemo {
    public int i=0;
    public synchronized void accessResource() {
        try {
            i++;
            TimeUnit.SECONDS.sleep(2);
            System.out.println(Thread.currentThread().getName()+"is running:" + i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SynchronizedDemo synchronizedDemo = new SynchronizedDemo();
        for (int i=0;i<5;i++){
            new Thread(synchronizedDemo::accessResource).start();
        }
    }
}

 3.修饰代码块

  3.1:synchronized (this):这里的this指的是当前对象,这个的原理是获取的对象锁。

public class SynchronizedDemo {
    public static int i=0;
    public void accessResource() {
        synchronized (this) {
            try {
                i++;
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName()+"is running:" + i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        SynchronizedDemo demo = new SynchronizedDemo();
        for (int i=0;i<5;i++){
            new Thread(demo::accessResource).start();
        }
    }
}

  3.2:synchronized (Class):这里的参数是一个类,使用这种方式,表示所有通过这个Class创建的对象都共享此同步代码块。这个的原理是获取类锁。

public class SynchronizedDemo {
    public static int i=0;
    public void accessResource() {
        synchronized (SynchronizedDemo.class) {
            try {
                i++;
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName()+"is running:" + i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        SynchronizedDemo demo = new SynchronizedDemo();
        SynchronizedDemo demo1 = new SynchronizedDemo();
        for (int i=0;i<5;i++){
            new Thread(demo::accessResource).start();
            new Thread(demo1::accessResource).start();
        }
    }
}

 4.Synchronized(Class)加锁的原理:

  在每个Java对象中都会有一个Monitor对象(也就是这个对象的监听器,原理是一个计数器),当某一个线程在占用这个对象的时候,首先判断这个monitor对象的计数器是不是0,如果是0,说明这个对象还没有被其他线程占用,这时候这个线程就可以占用这个对象了,并且把monitor+1。如果这个monitor不是0,则说明这个对象已经被别的线程给占用了,这个时候,此线程需要等待。当线程释放占用权的时候,monitor-1,。这时候通过 javap 命令查询反编译文件时,是有一个monitorenter和一个monitorexist与之对应的(但是在Synchronized修饰的方法时,是在方法标识中声明的,并没有monitorenter和monitorexist)。

5.JDK对Synchronized的优化:在jdk1.6之前,jvm只有一种重量级锁,在jdk1.6之后,jvm对Synchronized进行了优化,增加了偏向锁轻量级锁

  偏向锁的原理:是指在对象头信息中会记录一个线程id,如果是相同的线程来访问同步代码块,那么就相当于是无锁状态。

posted @ 2021-09-11 00:16  WK_BlogYard  阅读(45)  评论(0编辑  收藏  举报