首先说一下 lock 和 synchronized 的区别:
1:lock 是 java 语言的一个借口,synchronized 是 java 的关键字,是语言特性
2:synchronized 在 发生异常时,可以自动释放锁,因此不会发生死锁情况,而 lock 只能通过显式的 unlock() 释放,否则容易发生死锁情况。
3:lock 可以让等待的线程相应中断,而synchronized 会让等待的线程一直等待下去。
4:lock 可以知道是否成功获取锁,而 synchronized 却不知道
5:lock 可以有效提高并发读的效率,而 synchronized 只能进行串行操作。
总的来讲:如果资源竞争不激烈,两者的性能差不多,如果资源竞争比较激烈,lock 的性能明显优于synchronized。
具体测试代码,有点杂。
package concurrent;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/*
* @author: wjf
* @version: 2016年3月26日 上午11:40:08
*/
public class TestLock {
private Lock lock=new ReentrantLock();
private ReentrantReadWriteLock rwl=new ReentrantReadWriteLock();
private ArrayList<Integer> list=new ArrayList<Integer>();
public synchronized void get(Thread thread){
long start=System.currentTimeMillis();
while(System.currentTimeMillis()-start<=10){
System.out.println(thread.getName()+"is reading");;
}
System.out.println(thread.getName()+"reading is done");
}
public void get2(Thread thread){
rwl.readLock().lock();
try{
long start=System.currentTimeMillis();
while(System.currentTimeMillis()-start<=1){
System.out.println(thread.getName()+"is reading");
}
System.out.println(thread.getName()+"reading is done");
}finally{
rwl.readLock().unlock();
}
}
public void insert(Thread thread){
// 主要 如果这个锁声明在这个地方则没有任何效果,因为他是 局部的,每个thread 都会声明一个不同的锁
//private Lock lock=new ReentrantLock();
lock.lock();
try{
System.out.println(thread.getName()+"得到了锁");
for(int i=0;i<5;i++){
list.add(i);
}
System.out.println(list.size());
}catch(Exception x){
}finally{
System.out.println(thread.getName()+"释放了锁");
lock.unlock();
}
}
//测试 trylock()
public void insert2(Thread thread) throws InterruptedException{
// tryLock() 如果 无法获取锁 则,直接退出
//lock.tryLock(time, unit) 则会等待一定的时间
if(lock.tryLock(1, TimeUnit.MICROSECONDS)){
try{
System.out.println(thread.getName()+"得到了锁");
for(int i=0;i<100000;i++){
list.add(i);
}
System.out.println(list.size());
}catch(Exception x){
}finally{
System.out.println(thread.getName()+"释放了锁");
lock.unlock();
}
}
else{
System.out.println(thread.currentThread()+"获取锁失败");
}
}
public void insert3(Thread thread) throws InterruptedException{
lock.lockInterruptibly();
// lock.lock();
try{
System.out.println(thread.getName()+"获得了锁");
long startTime=System.currentTimeMillis();
for(;;){
if(System.currentTimeMillis()-startTime>10000){
break;
}
}
}finally{
System.out.println(Thread.currentThread().getName()+"执行finally");
lock.unlock();
System.out.println(thread.getName()+"释放了锁");
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
TestLock lock=new TestLock();
new Thread(){
public void run(){
lock.get2(Thread.currentThread());
}
}.start();
new Thread(){
public void run(){
lock.get2(Thread.currentThread());
}
}.start();
/* test interrupt()
*
MyThread thread1=new MyThread(lock);
MyThread thread2=new MyThread(lock);
thread1.start();
thread2.start();
try{
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
thread2.interrupt();
*/
// new Thread(){
// public void run(){
// try {
// lock.insert2(Thread.currentThread());
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
// }.start();
// new Thread(){
// public void run(){
// try {
// lock.insert2(Thread.currentThread());
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
// }.start();
}
}
class MyThread extends Thread{
private TestLock test=null;
public MyThread(TestLock test){
this.test=test;
}
public void run(){
try{
test.insert3(Thread.currentThread());
}catch(Exception e){
System.out.println(Thread.currentThread().getName()+"被中断了");
}
}
}
补充一点关于 synzhronized 的 内容
关于可重入性:(reentrant)
lock 和 synchronized 都是可重入的。
可重入性实际上表明了锁的分配机制是基于线程的而不是基于方法的。比如下面的例子:
加入method1 获取了锁,调用method2() ,则不需要再去申请锁,就可以执行method2(),
public synchronized void method1(){
method2()
}
public synchronized void method2(){
//
}