synchronized基本使用以及原理

1. 场景

      在并发编程中存在线程安全问题,主要缘由有:存在共享数据,多线程共同操做共享数据。关键字synchronized能够保证在同一时刻,只有一个线程能够执行某个方法或某个代码块,同时synchronized能够保证一个线程的可见性java

2. 概念

利用锁的机制来实现同步的(解决数据点不一致性 JMM)编程

  • 锁机制有以下两种特性
  1. 互斥性
    在同一时间只容许一个线程持有某个对象锁,经过这种特性来实现多线程中的协调机制,这样在同一时间只有一个线程对所需同步的代码块(复合操做)进行访问。互斥性也称为操做的原子性
  2. 可见性
    必须确保在锁被释放以前,对共享变量所作的修改,对于随后得到该锁的另外一个线程是可见的(即在得到锁时应得到最新共享变量的值),不然另外一个线程多是在本地缓存的某个副本上继续操做从而引发不一致。

3. synchronized的用法

  • 同步方法(分普通方法和静态方法)
    用法:只须要在方法上面添加synchronized关键字便可。
    同步普通方法:只能做用在单例上面,若是不是单例,同步方法锁将失效。
    同步静态方法:无论你有多少个类实例,同时只有一个线程能获取锁进入这个方法。
  • 同步对象实例
private static int m = 0;
 private Object obj = new Object();

 public void test1() {
     try {
         synchronized (obj) {
             TimeUnit.MINUTES.sleep(2);
             m++;
         }
     } catch (InterruptedException e) {
         e.printStackTrace();
     }
 }
  • 同步类

锁效果与同步静态方法同样,都是类级别的锁,同时只有一个线程能访问带有同步类锁的方法。缓存

public class synchronizedDemo {
    private static int m = 0;
    public void test2() {
        try {
            synchronized (synchronizedDemo.class) {
                TimeUnit.MINUTES.sleep(2);
                m++;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  • 同步this实例

与同步块的用法一致,表示锁住整个当前对象实例,只有获取到这个实例的锁才能进入这个方法。安全

private static int m = 0;
    public void test2() {
        try {
            synchronized (this) {
                TimeUnit.MINUTES.sleep(2);
                m++;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

4. synchronized底层语义原理

可经过工具jconsole和jstack去观察synchronized的底层以及线程状况。多线程

  • 方法锁:

方法锁就是由关键字ACC_SYNCHRONIZED实现是否互斥方法,并发

  • 对象锁:

monitor:在jvm规范中每一个对象和类在逻辑上都是和一个监视器(monitor)相关联的,为了实现监视器的排他性监视能力,JVM为每个对象和类都关联一个锁,锁住了一个对象,这就是得到对象相关联的监视器。
实现原理:某一个线程占有这个对象的时候,首先monitor的计数器是否是0,若是是0表示尚未线程占有这个时候线程占有这个对象,而且对这个对象的monitor+1;若是不为0表示这个对象已经被其余线程占有,这个线程等待。当线程释放占有权的时候monitor-1。
注:同一个线程能够对同一个对象屡次加锁,+1,+1,重入锁jvm

相关文章
相关标签/搜索