欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java Keyword Synchronized 学习记录

程序员文章站 2022-03-20 13:16:16
Synchronized Java编程思想:每个对象都包含了一把锁(也叫作“监视器”),它自动成为对象的一部分,调用任何synchronized方法时,对象就会被锁定,不可再调用那个对象的其他任何synchronized 方法,除非第一个方法完成了自己的工作,并解除锁定。 特点:Jvm层面,非公平, ......

synchronized

java编程思想:每个对象都包含了一把锁(也叫作“监视器”),它自动成为对象的一部分,调用任何synchronized方法时,对象就会被锁定,不可再调用那个对象的其他任何synchronized 方法,除非第一个方法完成了自己的工作,并解除锁定。
特点:jvm层面,非公平,悲观,独占,可重入,重量级。
作用:修饰方法和代码块。

修饰方法和代码块

synchronized修饰静态方法,我们可以称其为“类锁”,即只要有一个线程实例对象获取该锁,其他线程实例对象都需要等待。修饰非静态方法,我们称之为对象锁,即不同的线程实例对象是可以调用同一类下的同步方法。

/**
 * @packagename com.a.squirrel.synchronize
 * @author: squirrel
 * @date: 2018/6/25 10:04
 * @description: synchronized解析辅助类
 */
public class synchronizeddescription {

    private string tmpstr;

    private int tmpint;

    /**
      * @author squirrel
      * @description 非静态同步方法
      * @date 2018/6/25
      * @param [synchronizeddescription]
      * @return
     **/
    public synchronized void testsynchronizedmethod(synchronizeddescription synchronizeddescription){
        system.out.println("线程:"+synchronizeddescription.gettmpint()+"-->:==========我是非静态同步方法=======");
        system.out.println("线程:"+synchronizeddescription.gettmpint()+"-->:调用非静态同步方法时间为:"+getnowtime());
        try {
            thread.sleep(5000);// 当前线程休眠5s,休眠过程中不会释放锁
        } catch (interruptedexception e) {
            e.printstacktrace();
        }
    }

    /**
      * @author squirrel
      * @description 同步代码块
      * @date 2018/6/25
      * @param [synchronizeddescription]
      * @return
     **/
    public void testsynchronizedblockmethod(synchronizeddescription synchronizeddescription){
        synchronized (synchronizeddescription){// 锁定实例对象
            system.out.println("线程:"+synchronizeddescription.gettmpint()+"-->:==========我是同步代码块=======");
            system.out.println("线程:"+synchronizeddescription.gettmpint()+"-->:调用同步代码块时间为:"+getnowtime());
            try {
                thread.sleep(2000);// 当前线程休眠2s,休眠过程中不会释放锁
            } catch (interruptedexception e) {
                e.printstacktrace();
            }
        }
    }

    /**
      * @author squirrel
      * @description 静态同步方法
      * @date 2018/6/25
      * @param [synchronizeddescription]
      * @return
     **/
    public synchronized static void testsynchronizedstaticmethod(synchronizeddescription synchronizeddescription){
        system.out.println("线程:"+synchronizeddescription.gettmpint()+"-->:==========我是静态同步方法=======");
        system.out.println("线程:"+synchronizeddescription.gettmpint()+"-->:调用静态同步方法时间为:"+getnowtime());
        try {
            thread.sleep(10000);// 当前线程休眠10s,休眠过程中不会释放锁
        } catch (interruptedexception e) {
            e.printstacktrace();
        }
    }

    /**
      * @author squirrel
      * @description 获取当前时间
      * @date 2018/6/25
      * @param []
      * @return java.lang.string
     **/
    private static string getnowtime(){
        return new simpledateformat("yyyy-mm-dd hh:mm:ss").format(new date());
    }

    public synchronizeddescription(string tmpstr, int tmpint) {
        this.tmpstr = tmpstr;
        this.tmpint = tmpint;
    }

    public string gettmpstr() {
        return tmpstr;
    }

    public void settmpstr(string tmpstr) {
        this.tmpstr = tmpstr;
    }

    public int gettmpint() {
        return tmpint;
    }

    public void settmpint(int tmpint) {
        this.tmpint = tmpint;
    }
}
/**
 * @packagename com.a.squirrel.synchronize
 * @author: squirrel
 * @date: 2018/6/25 10:10
 * @description: 测试类
 */
public class testsynchronized {

    public static void main(string[] args) {
        // 创建阻塞队列
        final blockingqueue<runnable> queue = new arrayblockingqueue<>(100);
        // 创建线程池
        final threadpoolexecutor threadpool = new threadpoolexecutor(2,20,60, timeunit.seconds,queue);
        threadpool.allowcorethreadtimeout(true);
        for (int i =0;i<100;i++){
            threadpool.execute(new runnable() {
                @override
                public void run() {
                    final string tmpstr = thread.currentthread().getname();
                    final string[] split = tmpstr.split("-");
                    int tmpint = integer.parseint(split[split.length-1]);
                    synchronizeddescription synchronizeddescription = new synchronizeddescription(tmpstr,tmpint);
                    // 调用同步代码块
                    synchronizeddescription.testsynchronizedblockmethod(synchronizeddescription);
                    // 调用非静态同步方法
                    synchronizeddescription.testsynchronizedmethod(synchronizeddescription);
                    // 调用静态同步方法
                    synchronizeddescription.testsynchronizedstaticmethod(synchronizeddescription);
                }
            });
        }
    }
}

运行结果可以验证以上结论:
Java Keyword Synchronized 学习记录
下面我们变更同步代码块的同步对象:

    /**
      * @author squirrel
      * @description 同步代码块
      * @date 2018/6/25
      * @param [synchronizeddescription]
      * @return
     **/
    public void testsynchronizedblockmethod(synchronizeddescription synchronizeddescription){
        synchronized (synchronizeddescription.class){// 锁定类对象
            system.out.println("线程:"+synchronizeddescription.gettmpint()+"-->:==========我是同步代码块=======");
            system.out.println("线程:"+synchronizeddescription.gettmpint()+"-->:调用同步代码块时间为:"+getnowtime());
            try {
                thread.sleep(2000);// 当前线程休眠2s,休眠过程中不会释放锁
            } catch (interruptedexception e) {
                e.printstacktrace();
            }
        }
    }

Java Keyword Synchronized 学习记录
由上图我们可以得出一个结论,这里借用一张图来说明一下这个结论:
Java Keyword Synchronized 学习记录

实现原理:

深入理解java虚拟机:对象在内存中存储的布局可以分为3块区域:对象头,实例数据和对齐填充。
Java Keyword Synchronized 学习记录
synchronized对象锁其指针指向的是一个monitor对象,每个对象实例都会有一个 monitor,其中monitor可以与对象一起创建销毁,也可以在线程试图获取对象锁时自动生成。在执行monitorenter指令时,首先要尝试获取对象锁,如果这个对象没有被锁定,或者当前线程已经拥有了这个对象的锁,那么就把锁计数器加1,当执行monitorexit指令时,释放锁同时锁计数器也会减1。
Java Keyword Synchronized 学习记录Java Keyword Synchronized 学习记录