阿八博客
  • 100000+

    文章

  • 23

    评论

  • 20

    友链

  • 最近新加了很多技术文章,大家多来逛逛吧~~~~
  • 喜欢这个网站的朋友可以加一下QQ群,我们一起交流技术。

java并发synchronized的原理和应用

欢迎来到阿八个人博客网站。本 阿八个人博客 网站提供最新的站长新闻,各种互联网资讯。 喜欢本站的朋友可以收藏本站,或者加QQ:我们大家一起来交流技术! URL链接:https://www.abboke.com/jsh/2019/0930/116269.html

java并发编程这个领域中synchronized关键字一直都是元老级的角色,在java早期版本中,synchronized属于重量级锁,效率低下,因为监视器锁(monitor)是依赖于底层的操作系统的Mutex Lock来实现的,java的线程是映射到操作系统的原生线程之上的
如果要挂起或者唤醒一个线程,都需要操作系统帮忙完成,而操作系统实现线程之间的切换时需要从用户态转换到内核态,这个状态之间的转换需要相对比较长的时间,时间成本相对较高
在JDK1.6之后java官方对从JVM层面对synchronized 较大优化,所以现在的synchronized锁效率也优化得很不错
JDK1.6对锁的实现引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销

synchronized实现原理

通过反编译下面的代码来看看Synchronized是如何实现对代码块进行同步的,切换到类的对应目录执行javac SynchronizedTest.java命令生成编译后的.class文件,然后执行javap -v SynchronizedTest.class

1)synchronized同步代码块

public class SynchronizedTest {    public static void main(String[] args) {        new SynchronizedTest().method();    }    public void method() {        synchronized (this) {            System.out.println("synchronized 代码块");        }    }}


多个线程访问的是同一个对象,哪个线程先执行带synchronized关键字的方法,则哪个线程就持有该方法,那么其他线程只能呈等待状态
如果多个线程访问的是多个对象则不一定,因为多个对象会产生多个锁

3)脏读
发生脏读的情况实在读取实例变量时,此值已经被其他线程更改过

public class PublicVar {    public String username = "A";    public String password = "AA";    synchronized public void setValue(String username, String password) {        try {            this.username = username;            Thread.sleep(3000);            this.password = password;            System.out.println("setValue method thread name="                    + Thread.currentThread().getName() + " username="                    + username + " password=" + password);        } catch (InterruptedException e) {            e.printStackTrace();        }    }    //该方法前加上synchronized关键字就同步了    public void getValue() {        System.out.println("getValue method thread name="                + Thread.currentThread().getName() + " username=" + username                + " password=" + password);    }    public static void main(String[] args) {        try {            PublicVar publicVarRef = new PublicVar();            ThreadC thread = new ThreadC(publicVarRef);            thread.start();            Thread.sleep(500);//打印结果受此值大小影响            publicVarRef.getValue();        } catch (InterruptedException e) {            e.printStackTrace();        }    }    static class ThreadC extends Thread {        private PublicVar publicVar;        public ThreadC(PublicVar publicVar) {            this.publicVar = publicVar;        }        @Override        public void run() {            publicVar.setValue("B", "BB");        }    }}

相关文章

暂住......别动,不想说点什么吗?
  • 全部评论(0
    还没有评论,快来抢沙发吧!