使用多线程,不可避免会碰上同个资源争抢的问题,即线程同步问题。比如节假日的抢票,多个人同时申请买票时,都会让票数减一,如何确保票数正确,不会发生超卖问题?答案是等待,虽然是同步请求,但后台同一时刻只处理一个请求,其它请求等待,就能确保争抢资源——票数正确。
同样的,线程同步其实就是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面线程使用完毕,下一个线程再使用。
为了确保每次只有一个线程处理,可以使用锁机制,每个正在处理的线程都持有对象的锁,处理完之后再释放锁。没有持有锁的线程,继续等待。
二、sysnchronized线程同步锁之一是sysnchronized关键字。它有两种用法:
1、syschronized方法。直接在需要同步的方法上加个syschronized关键字,就能达到同步的目的。有时候如果将整个大方法都声明为syschronized同步的话,将会影响效率。这时候可以使用syschronized块的方法。
2、syschronized块。syschronized(Obj){(需要同步执行的代码)},Obj可以是任何对象,推荐是使用共享资源,比如抢票中的火车票数量这个对象。
同步方法中无需指定同步对象,因为同步方法的同步对象就是this,也就是调用该方法的对象本身。
syschronized可以理解为是一种自动上锁解锁的机制,它无需程序员自己控制上锁解锁动作,全自动完成。
三、Lock从JDK5.0开始,Java提供了更强大的线程同步机制——通过显示定义同步锁Lock对象来实现同步。
ReettrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存语义,显示的加锁、释放锁。
代码示例:
class A {
private final ReentrantLock lock = new ReenTrantLock();
public void m() {
lock.lock();
try {
// 需要确保线程安全的代码
} catch......
finally {
lock.unlock();
// 如果同步代码有异常,要将unlock()写入finally语句块
}
}
}
synchronized与Lock的对比:
1、Lock是显示锁,需要手动开启和关闭锁,synchronized是隐式锁,到了作用域自动上锁,出了作用域自动释放锁;
2、Lock只有代码块锁,synchronized有代码块锁和方法锁;
3、使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有较好的扩展性,比如提供更多的子类。
4、优先使用顺序:Lock > synchronized同步代码块 > synchronized同步方法



