四、Synchronized与Lock原理

1,369 阅读3分钟

6、Synchronized与Lock原理

1)、Synchronized与Lock区别:
    a)、synchronized是一个关键字,在代码执行时出现异常,JVM会自动释放锁,
	Lock是一个接口,要保证锁被释放,就必须在finally中执行unLock();
    b)、synchronized属于隐式锁,不能实现公平锁;
	Lock是显式锁,可实现公平锁,可以对锁进行控制,可以中断
    c)、synchronized作用在static方法上时候,为全局锁;作用在非static方法上时,为对象锁

2)、Synchronized原理:
	Synchronized作用于方法时:
		JVM可以从方法常量池中的方法表结构(method_info Structure) 中的 
		ACC_SYNCHRONIZED访问标志区分一个方法是否同步方法。当方法调用时,
		调用指令将会 检查方法的ACC_SYNCHRONIZED访问标志是否被设置,
		如果设置了,执行线程将先持有monitor,然后再执行方法,最后再方法完成
		(无论是正常完成还是非正常完成)时释放monitor。在方法执行期间,
		执行线程持有了monitor,其他任何线程都无法再获得同一个monitor。
		如果一个同步方法执行期间抛 出了异常,并且在方法内部无法处理此异常,
		那这个同步方法所持有的monitor将在异常抛到同步方法之外时自动释放。
	Synchronized作用于同步代码块时:
	    通过一个monitor(监视器锁)的对象来完成,使用monitorenter 和 monitorexit指令,
	    monitorenter指令指向同步代码块的开始位置,monitorexit指令则指明同步代码块的
	    结束位置,当执行monitorenter指令时当monitor被占用时就会处于锁定状态,线程执行
	    monitorenter指令时尝试获取对象所对应的monitor所有权,倘若其他线程已经拥有
	    对象的 monitor所有权,那当前线程将被阻塞,直到正在执行线程执行完毕,
	    即monitorexit指令被执行。流程如下:
        	a)、如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,
        	   该线程即为monitor的所有者。
                b)、如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1.
                c)、如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的
                    进入数为0,再重新尝试获取monitor的所有权。

3)、Lock原理:
	Lock实现类是ReetrantLock。ReetrantLock是基于AQS(AbstractQueuedSynchronizer又
	称为队列同步器)并发框架实现的。
	AQS原理:
		内部通过一个int类型的成员变量state来控制同步状态,当state=0时,则说明没有
		任何线程占有共享资源的锁,当state=1时,则说明有线程目前正在使用共享变量,
		其他线程必须加入同步队列(FIFO的双向链表队列)进行等待,AQS内部通过
		内部类Node构成FIFO的同步队列来完成线程获取锁的排队工作,同时利用内部类
		ConditionObject构建等待队列,当Condition调用wait()方法后,线程将会加入
		等待队列中,而当Condition调用signal()方法后,线程将从等待队列转移动
		同步队列中进行锁竞争。注意这里涉及到两种队列,一种的同步队列,当线程请求锁
		而等待的后将加入同步队列等待,而另一种则是等待队列(可有多个),通过Condition
		调用await()方法释放锁后,将加入等待队列。
	ReetrantLock原理:
		重入锁ReentrantLock,是一个基于AQS并发框架的并发控制类,其内部实现了3个类,
		分别是Sync、NoFairSync、FairSync类,其中Sync继承自AQS,实现了释放锁的
		模板方法tryRelease(int),而NoFairSync和FairSync都继承自Sync,实现各种
		获取锁的方法tryAcquire(int)。ReentrantLock的所有方法实现几乎都间接调用了
		这3个类

附上一个ReentrantLock(源码解析流程)流程图(网上找的):