java线程中数据同步-lock
作者:bin除了使用synchronized修饰代码块或者方法,还可以使用Lock方式添加锁,不过要自己释放锁。
区别:
synchronized:是java语言的关键字,是原生语法层面的互斥,需要jvm实现
ReentrantLock:它是JDK 1.5之后提供的API层面的互斥锁,需要lock()和unlock()方法配合try/finally语句块来完成,并且又trylock设置超时放弃锁(trylock()方法未获取到锁后会返回false)
/** * ReentrantLock功能和synchronized一致 */ Lock lock = new ReentrantLock(); /** * ReentrantReadWriteLock是读写分离锁 */ //Lock lock = new ReentrantReadWriteLock().readLock(); try { //代码块串行,锁上 lock.lock(); System.out.println("nihao"); }finally { //解锁 lock.unlock(); }
ReentrantLock(独占锁)的实现原理:
reentranlock:
1.使用state状态来保存锁的占用情况,>1表示锁被占用了。
2.可重入的实现实际上每加一次锁,是对state进行+1,解锁对state-1
3.如果锁未被占用,那么会使用cas进行比较然后设置+1,保证线程安全
4.公平锁:如果锁被占用了,那么新来的线程将加入一个双线链表的表尾,从表头读出一个线程任务,尝试获得锁。
5.非公平锁:如果锁被占用,先尝试获取锁状态,获取不到即进入链表尾部,从表头读出一个线程任务,尝试获得锁。
ReentrantLock的Condition:
类似synchronized的中使用wait呢notify,差异是synchronized中只能对当前锁定对象进行wait即1对1,而lock可以1对多condition。
首先定义一个condition
Lock lock = new ReentrantLock(); Condition con = lock.newCondition();
使用wait
con.await();
使用notify
con.signal(); //con.signalAll();
Semaphore (共享锁)的实现原理
ReetranLock是独占锁,Semaphore是共享锁,
实现的原理和独占锁类似,都是使用Sync类来做的:
1.Semaphore可以设置锁的数量,即同时多少个线程可以并行执行。
2.内部也是通过state去做的,初始化是设置一个state数量,增加线程时对state-1
3.state = 0,表示达到最大线程数量,即锁都被用完了。
4.1.公平锁,新加入的线程先判断是否有等待队列,有就加入队列,没再获取锁。
4.2.非公平锁(默认),新加入的线程先获取锁,获取不到再加入等待队列。原理和reetranlock一样