HashMap是线程非安全的,怎么能线程安全呢,这时候hashtable就出现了,hashmap允许放null,且有且只有一个null,因为不能key不能重复,hashtable不允许放null。
Hashtable的源码里都上了synchronized锁,导致效率低。
这时候这篇文章的主角currentHashmap就出现了。
currentHashmap1.7之前都是实现Reentrantlock,并不是整个代码都上锁,而是需要线程安全的地方上锁,这样运行效率远远高于hashtable,他把内部分成许多segment,然后分别给需要上锁的地方上锁。
说到synchronized和Reentrantlock,就可以来聊一下他们两个的区别?
他们都是io阻塞锁,线程运行的时候,如果被另一个线程加锁,需要等另一个线程运行完,才能运行。
Synchronized会自己自动释放锁,Reentrantlock则需要自己手动释放锁,而且手动释放锁必须放在finally里面unlock,建议新手用前者。
Reentrantlock是可以公平,可以中断响应,限制等待时间。
1、Lock()会一直等待锁获取到,可以设置公平锁。
公平锁指当锁可用时,会让等待时间最长的线程获取锁。非公平锁指随便分配线程获取锁。
2、LockInterruptibly()可以也会等待获取,但可以自行中断。
3、Trylock方法判断当前线程是否能获取到锁,获取到返回true,没有获取到返回false,还可以设定过期时间。
场景一公平锁的实现:
/** * 公平锁 * * @param args */ public static void main(String[] args) { ReentrantLock lock = new ReentrantLock(); for (int i = 0; i < 5; i++) { Thread thread = new Thread(new TestThread(i)); thread.start(); } } static class TestThread implements Runnable { Integer z; public TestThread(Integer i) { this.z = i; } @Override public void run() { try{ Thread.sleep(1000); }catch (Exception e){ } for (int i = 0; i < 2; i++) { System.out.println(Thread.currentThread().getName()+"==="+z); } } }
公平锁的结果,为了更好地获取信息,让线程休息1s,可以看到公平锁几乎都是轮流获取:
非公平锁的,线程则会重复获取锁:
场景二:
/** * 中断响应实例 */ public static void main(String[] args) { ReentrantLock lock1 = new ReentrantLock(); Thread thread1 = new Thread(new TestThread(lock1)); Thread thread2 = new Thread(new TestThread2(lock1)); thread1.start(); thread2.start(); //中断线程 thread2.interrupt(); } static class TestThread implements Runnable { Lock firstName; public TestThread(Lock firstName) { this.firstName = firstName; } @Override public void run() { try { System.out.println("进入" + Thread.currentThread().getName()); firstName.lockInterruptibly(); Thread.sleep(5000); } catch (Exception e) { } finally { firstName.unlock(); System.out.println(Thread.currentThread().getName() + "结束!!"); } } } static class TestThread2 implements Runnable { Lock firstName; public TestThread2(Lock firstName) { this.firstName = firstName; } @Override public void run() { try { System.out.println("进入" + Thread.currentThread().getName()); firstName.lockInterruptibly(); Thread.sleep(5000); } catch (Exception e) { } finally { firstName.unlock(); System.out.println(Thread.currentThread().getName() + "结束!!"); } } }
线程中断之后,则就不会一直等待。
场景三:
/** * 限制时间trylock */ public static void main(String[] args) { ReentrantLock reentrantLock = new ReentrantLock(); Thread thread0 = new Thread(new TestThread0(reentrantLock)); thread0.start(); Thread thread1 = new Thread(new TestThread1(reentrantLock)); thread1.start(); } } class TestThread0 implements Runnable { ReentrantLock reentrantLock; public TestThread0() { } public TestThread0(ReentrantLock reentrantLock) { this.reentrantLock = reentrantLock; } @Override public void run() { if (reentrantLock.tryLock()) { try { System.out.println("进入" + Thread.currentThread().getName()); Thread.sleep(7000); } catch (InterruptedException e) { e.printStackTrace(); } } } } class TestThread1 implements Runnable { ReentrantLock reentrantLock; public TestThread1() { } public TestThread1(ReentrantLock reentrantLock) { this.reentrantLock = reentrantLock; } @Override public void run() { if (reentrantLock.tryLock()) { try { System.out.println("进入" + Thread.currentThread().getName()); Thread.sleep(7000); } catch (InterruptedException e) { e.printStackTrace(); } } }
当前trylock只会返回一个true,另一个返回false,未获取到锁。