012 内置锁和synchronized

一 . 概述

在前面我们说到线程安全性问题解决的核心就是同步,同步的核心就是保证原子性.

在java之中最早就支持语法层面的同步解决了,并且提供了synchronized的方式解决问题.


二 .内置锁

  在java之中每一个对象都是一个内置锁,这个在JVM的体系之中就规定好了.

  内置锁的规定也就决定我们可以拿任意的对象进行同步操作.

内置锁常常配合synchronized使用.


三 .synchronized 

  该关键词的作用是同步,需要配合内置锁进行使用.

    常见的synchronized的使用方式有三种:

     [1]在静态方法中使用

     [2]在实例方法中使用

     [3]在同步代码块之中使用

  其中: 在静态方法之中的内置锁是该类的class对象,实例方法的内置锁是调用该方法的实例对象.

    在同步代码块之中的内置锁需要显示的指定.


四 . 例子

  将我们之前的计数代码进行改写,变成线程安全的操作. 

public class ProblemSolve {
    
    private int count = 0;
    
    public static void main(String[] args) throws Exception {
        ProblemSolve demo = new ProblemSolve();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int x =0;x<10000;x++) {
                    demo.add();
                }
            }
            
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int x =0;x<10000;x++) {
                    demo.add();
                }
            }
            
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("获取最终的结果count : " + demo.count);
        
    }
    private synchronized void add() {
        count++;
    }
}

我们所作出的概念仅仅是加上了一个synchronized关键词就完成了同步的操作,这样我们就能保证线程安全性.


五 .分析

  当我们的代码进入同步代码的时候,会试图获取内置锁.

  获取成功: 继续运行

  获取失败: 进入该内置所的阻塞队列.直到获取该所的线程完成任务或者自己释放内置所的拥有权.

        然后阻塞队列的线程重新进入runnable状态,再此尝试获取该锁.

  以上就是synchronized同步的底层运行方式.


六. synchronized的优劣

  优势 : 保证原子性,因为同步的代码仅仅只有一个线程可以运行.

  劣势: 粒度过大,获取不到内置锁的线程会进入阻塞队列等待唤醒,这个是一刀切的方式,很有可能会影响性能.

解决: 在jak6之后,对synchronized关键词的实现进行了优化,这个在下面会介绍.

猜你喜欢

转载自www.cnblogs.com/trekxu/p/8996090.html