在java中实现的同步的方式有synchronized方法,synchronized代码块,ReentranLock,ReentrantReadWriteLock,
主要功能是在多线程的环境下实现代码的同步。
synchronized方法,有一定的局限性作用的区域受限,有时代码可能只需要方法中某一行或者几行代码要同步,不许要整个方法同步影响程序性能或则造成程序错误。这个时候可以使用synchronized代码块,而且代码块有更灵活的锁机制可以使用自定义的对象作为锁,也可以使用当前对象作为锁。下面对比下 lock 和 synchronized:
1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现发象生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
5)Lock可以提高多个线程进行读操作的效率。
ReentrantReadWriteLock更是可以对读写两种不同的情况分别加锁。具体情景如下:写的时候不能读取数据,而且写之间是互斥的,读的时候不互斥。代码如下:
public class ReadWriterLock { public static void main(String[] args) { final Queue3 q3 = new Queue3(); for (int i = 0; i < 3; i++) { new Thread() { public void run() { while (true) { q3.get(); } }; }.start(); new Thread() { public void run() { while (true) { q3.put(new Random().nextInt(10000)); } }; }.start(); } } } class Queue3 { private Object data = 0; private ReadWriteLock rwL = new ReentrantReadWriteLock(); public void get() { rwL.readLock().lock(); try { System.out.println(Thread.currentThread().getName() + " ready read data!"); Thread.sleep((long) (Math.random() * 1000)); System.out.println(Thread.currentThread().getName() + "have read data!"+this.data.toString()); } catch (InterruptedException e) { e.printStackTrace(); }finally{ rwL.readLock().unlock(); } } public void put(Object data) { rwL.writeLock().lock(); try { System.out.println(Thread.currentThread().getName() + " ready write data!"); this.data = data; Thread.sleep((long) (Math.random() * 1000)); System.out.println(Thread.currentThread().getName() + "have write data!"+this.data.toString()); } catch (InterruptedException e) { e.printStackTrace(); }finally{ rwL.writeLock().unlock(); } } }
以上实现了写和读之间的互斥。使用此特点可以设计一个缓存系统:代码如下
ConcurrentHashMap<String, String> hashMap=new ConcurrentHashMap<>(); public String get(String key){ ReadWriteLock readWriteLock=new ReentrantReadWriteLock(); readWriteLock.readLock().lock(); if(hashMap.containsKey(key)){ return hashMap.get(key); }else{ readWriteLock.readLock().unlock(); readWriteLock.writeLock().lock(); String db=null; if(!hashMap.containsKey(key)){ db=new Random()+"123aaa"; hashMap.put(key,db); } readWriteLock.writeLock().unlock(); return db; } }