参考链接
Java锁–Lock实现原理(底层实现)
Lock与synchronized的区别和性能比较
Lock和synchronized的区别和使用
synchronized关键字和lock接口的区别
- lock是一个接口,而synchronized是java的一个关键字,synchronized是内置的语言实现。
- synchronized在发生异常时候会自动释放占有的锁,因此不会出现死锁;而lock发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生,因此lock的unlock方法一般都是必须放在finally里面的。
- lock等待锁过程中可以用interrupt来中断等待,而synchronized只能等待锁的释放,不能响应中断。
- lock可以通过trylock来知道有没有获取锁,而synchronized不能;。
- Lock可以提高多个线程进行读操作的效率,可以通过readwritelock实现读写分离。
lock接口
lock的源码
public interface Lock {
//获取锁,如果锁被暂用则一直等待
void lock();
//通过这种方式获取锁,会中断其他线程的锁等待。
void lockInterruptibly() throws InterruptedException;
//注意返回类型是boolean,如果获取锁的时候锁被占用就返回false,否则返回true
boolean tryLock();
//比起tryLock()就是给了一个时间期限,保证等待参数时间
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
//释放锁
void unlock();
Condition newCondition();
}
lock的一般使用案例
package com.madman.base.concurr;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest{
private Lock lock = new ReentrantLock();
//需要参与同步的方法
private void method(Thread thread) {
lock.lock();
try {
System.out.println("线程名" + thread.getName() + "获得了锁");
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("线程名" + thread.getName() + "释放了锁");
lock.unlock();
}
}
public static void main(String[] args) {
final LockTest lockTest = new LockTest();
//线程1
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
lockTest.method(Thread.currentThread());
}
}, "t1");
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
lockTest.method(Thread.currentThread());
}
}, "t2");
t1.start();
t2.start();
}
}
结果
运行结果发现是谁先获得锁谁就先执行,可以在中间添加线程添加睡眠来试一下。
这里使用的是lock.lock(),lock.tryLock()的使用和这个基本差不多,只不过lock.tryLock()有个返回值,你可以根据这个返回值进行特定判断。
线程名t1获得了锁
线程名t1释放了锁
线程名t2获得了锁
线程名t2释放了锁
lock接口的ReadWriteLock和ReentrantReadWriteLock
ReentrantReadWriteLock类实现了ReadWriteLock接口,ReadWriteLock接口还有两个方法
Lock readLock();
Lock writeLock();
关于ReadWriteLock和ReentrantReadWriteLock的使用参考
Lock和synchronized的区别和使用