日积月累--Lock锁机制

对象监视器

  什么是监视器?

  监视器可以看做是经过特殊布置的建筑,这个建筑有一个特殊的房间,该房间通常包含一些数据和代码,但是一次只能一个消费者(thread)使用此房间,

  

当一个消费者(线程)使用了这个房间,首先他必须到一个大厅(Entry Set)等待,调度程序将基于某些标准(e.g. FIFO)将从大厅中选择一个消费者(线程),进入特殊房间,如果这个线程因为某些原因被“挂起”,它将被调度程序安排到“等待房间”,并且一段时间之后会被重新分配到特殊房间,按照上面的线路,这个建筑物包含三个房间,分别是“特殊房间”、“大厅”以及“等待房间”。

简单来说,监视器用来监视线程进入这个特别房间,他确保同一时间只能有一个线程可以访问特殊房间中的数据和代码。

  监视器 的实现    

在JAVA虚拟机中,每个对象(Object和class)通过某种逻辑关联监视器,为了实现监视器的互斥功能,每个对象(Object和class)都关联着一个锁(有时也叫“互斥量”),这个锁在操作系统书籍中称为“信号量”,互斥(“mutex “)是一个二进制的信号量。

如果一个线程获得了某些数据上的一个锁(lock),那么,直到该线程释放该锁之前,其他的线程都无法获取该锁。如果我们在进行多线程编程时,每次都需要获取信号、操作信号、释放信号等操作,那么多线程的编程体验将是非常不愉快的。幸运的是,我们并不需要这么做,JVM在底层帮我们把这些繁琐的细节做完了。

为了声明一个监控区域,该监控区域最多只允许一个客户(线程)访问,Java提供了 同步语句(synchronization statements) 和 同步方法(synchronization methods) 两种便利机制。一旦某个代码块被 synchronized 关键词包围,该代码块就变成了一个监控区域。同时,该监控区域对应的二元信号,由JVM在底层自动生成并维护着。

  

 AQS(AbstractQueuedSynchronized)抽象的队列式的同步器

  AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock/Semaphore/CountDownLatch… 

AQS维护了一个volatile int state(代表共享资源)和一个FIFO线程等待队列(多线程争用资源被阻塞时会进入此队列)。state的访问方式有三种:

getState()
setState()
compareAndSetState()


volatile

synchronized修饰静态方法,相当于其锁的对象时class。如果class还有其他的synchronized修饰的静态方法,都是同步的。

 
原文地址:https://www.cnblogs.com/520lq/p/10622002.html