JAVA

9.锁相关和synchronized关键字

2020-03-03  本文已影响0人  强某某
  1. JAVA中锁的概念
  1. 同步关键字synchronized
    属于最基本的线程通信机制,基于对象监视器实现的。Java中的每个对象都与一个监视器相关联,一个线程可以锁定或解锁。
    一次只有一个线程可以锁定监视器,试图锁定该监视器的任何其他线程都会被阻塞,直到它们可以获得该监视器上的锁定为止。
public class ObjectSyncDemo {

    public synchronized void test() {
        try {
            System.out.println(Thread.currentThread()+"开始执行");
            Thread.sleep(3000L);
            System.out.println(Thread.currentThread()+"执行结束");
        } catch (Exception e) {

        }
    }

    public static void main(String[] args) throws InterruptedException {
        new Thread(()->{
            new ObjectSyncDemo().test();
        }).start();
        Thread.sleep(1000L);
        new Thread(()->{
            new ObjectSyncDemo().test();
        }).start();
    }
}
Thread[Thread-0,5,main]开始执行
Thread[Thread-1,5,main]开始执行
Thread[Thread-0,5,main]执行结束
Thread[Thread-1,5,main]执行结束

此时结果输出如上:因为synchronized此时是对象锁,new ObjectSyncDemo就是新对象,两者互不影响

public class ObjectSyncDemo {

    public synchronized static void test() {
        try {
            System.out.println(Thread.currentThread()+"开始执行");
            Thread.sleep(3000L);
            System.out.println(Thread.currentThread()+"执行结束");
        } catch (Exception e) {

        }
    }

    public static void main(String[] args) throws InterruptedException {
        new Thread(()->{
            new ObjectSyncDemo().test();
        }).start();
        Thread.sleep(1000L);
        new Thread(()->{
            new ObjectSyncDemo().test();
        }).start();
    }
}
Thread[Thread-0,5,main]开始执行
Thread[Thread-0,5,main]执行结束
Thread[Thread-1,5,main]开始执行
Thread[Thread-1,5,main]执行结束

此时static已经是类锁了,即两个线程是同一把锁,所以才依次执行

> 此时也是对象锁,不会依次执行
public class ObjectSyncDemo {

    public void test() {
        try {
            synchronized (this) {
                System.out.println(Thread.currentThread() + "开始执行");
                Thread.sleep(3000L);
                System.out.println(Thread.currentThread() + "执行结束");
            }
        } catch (Exception e) {

        }
    }

    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            new ObjectSyncDemo().test();
        }).start();
        Thread.sleep(1000L);
        new Thread(() -> {
            new ObjectSyncDemo().test();
        }).start();
    }
}
> 此时是类锁,依次执行
public class ObjectSyncDemo {
    // static Object o=new Object();
    public void test() {
        try {
            synchronized (ObjectSyncDemo.class) {
            // synchronized (0) {  此时也是类级别的锁,会依次执行
                System.out.println(Thread.currentThread() + "开始执行");
                Thread.sleep(3000L);
                System.out.println(Thread.currentThread() + "执行结束");
            }
        } catch (Exception e) {

        }
    }

    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            new ObjectSyncDemo().test();
        }).start();
        Thread.sleep(1000L);
        new Thread(() -> {
            new ObjectSyncDemo().test();
        }).start();
    }
}
  1. 可重入锁
public class ObjectSyncDemo {
    public synchronized void test(Object arg) {
        System.out.println(Thread.currentThread()+"开始执行"+arg);
        if (arg==null) {
            test(new Object());
        }
        System.out.println(Thread.currentThread()+"执行结束"+arg);
    }

    public static void main(String[] args) throws InterruptedException {
            new ObjectSyncDemo().test(null);
    }
}

Thread[main,5,main]开始执行null
Thread[main,5,main]开始执行java.lang.Object@16d3586
Thread[main,5,main]执行结束java.lang.Object@16d3586
Thread[main,5,main]执行结束null
  1. 锁粗化
    所谓锁粗化:就是jit在运行时动态的在不影响结果的情况下扩大锁的范围从而优化性能
//锁粗化(运行时jit编译优化)
//jit编译后的汇编内容,jitwatch可视化工具查看
public class ObjectSyncDemo {
    int i;
    public synchronized void test(Object arg) {
        synchronized (this) {
            i++;
        }
        synchronized (this) {
            i++;
        }
        //再jit判断运行次数,从而局部优化代码,如上一万次,会被优化成如下
//        synchronized (this) {
//            i++;
//            i++;
//        }
    }

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 100000; i++) {
            new ObjectSyncDemo().test(null);
        }
    }
}
  1. 锁消除
import javax.management.ObjectName;

public class ObjectSyncDemo {
    public void test3(Object arg) {
        StringBuilder sb=new StringBuilder();
        sb.append("a");
        sb.append("b");
        sb.append("c");
        System.out.println(arg.toString());
    }
    public void test2(Object arg) {
        String a="a";
        String c="c";
        System.out.println(a+arg+c);
    }
    public void test1(Object arg) {
        //jit优化,消除锁,因为StringBuffer是线程安全的,append点击去看,都有synchronized
        //锁消除之后,就会发现锁被取消了,没有锁了;之所以如此也是为了提高性能,因为循环次数太多了
        StringBuffer stringBuffer=new StringBuffer();
        stringBuffer.append("a");
        stringBuffer.append(arg);
        stringBuffer.append("c");
    }

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 1000000; i++) {
            new ObjectSyncDemo().test1("123");
        }
    }
}
  1. 同步关键字加锁原理


    3.png
上一篇 下一篇

猜你喜欢

热点阅读