为什么会有线程安全???
例如生活中抢购 买票问题,当你查询到有剩余车票时,只要你能够进入支付界面时候你肯定会买到这张票,因为这张票或者说资源已经被你锁定了,只要你不取消或者说是释放资源,其他人是无法买到这张票的,
那问题又来了,线程安全为嘛又扯到锁上面来了?
其实线程安全是用锁实现的,下面就介绍几种锁来实现线程安全。
1 synchronized
用于修饰方法
public synchronized void getTicket()
优点:实现线程安全,资源只能被当前线程访问
缺点:线程串行化,效率低,只能等前一个线程完全走完之后,下一个线程才能进入,如上厕所这件事情,在别人上厕所时候起码你可以拿纸在外面等,不至于非要等别人上完厕所后,你再去拿纸。
所以 synchronized 衍生到 在方法内部执行
System.out.println(Thread.currentThread().getName()+” : 拿纸…”);
synchronized (this) {
System.out.println(Thread.currentThread().getName()+” : 上厕所…”);
System.out.println(Thread.currentThread().getName()+” : 出厕所”);
}
System.out.println(Thread.currentThread().getName()+” : 上完厕所,真舒服,洗个手 … end”);
衍生到内部之后,锁定的内容就是上厕所和出厕所,其他流程就不用排队。
然而衍生到方法内部,还有另一种加锁方式可以实现线程安全。
2 ReentrantLock lock对象
System.out.println(Thread.currentThread().getName() + " : 拿纸...");
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " : 上厕所...");
System.out.println(Thread.currentThread().getName() + " : 出厕所");
System.out.println(Thread.currentThread().getName() + " : 上完厕所,真舒服,洗个手 ... end");
} finally {
// 3.使用Lock对象的unlock方法解锁
lock.unlock();
跟 synchronized 相比需要主动加锁和释放。
注意:可把解锁的unlock方法的调用放在finally{}代码块中,保证一定能解锁
提醒:在同步的时候,其他代码都可以多个线程同时执行!只是被同步的代码不能同时执行!
那什么时候用lock 什么时候用 synchronized ??
在并发量比较小的情况下,使用synchronized是个不错的选择,但是在并发量比较高的情况下,其性能下降很严重,此时Lock是个不错的方案。