在JDK1.5中新增了一个java.util.concurrent包来支持同步。
使用JUC里的Lock与使用synchronized方法和块具有相同的基本行为和语义,并且扩展了其能力
关键字synchronized实现的同步的锁,是隐藏的,所以并不明确是在哪里加上了锁,在哪里释放了锁。为了更明确的控制从哪里开始锁,在哪里释放锁,JDK1.5提供了Lock。
Lock是一个接口,真正用的是它的实现类ReentrantLock。
public class ThreadTest {
public static void main(String[] args) {
synchronizeThread st = new synchronizeThread();
new Thread(st, "1").start();
new Thread(st, "2").start();
new Thread(st, "3").start();
new Thread(st, "4").start();
}
}
class synchronizeThread implements Runnable {
private Integer ticketNumber = 100;
private Lock lock = new ReentrantLock();//创建一个重入锁对象
@Override
public void run() {
for (int i = 0; i < 100; i++) {
lock.lock();//开启锁
try {
if (ticketNumber > 0) {
System.out.println("线程【" + Thread.currentThread().getName() + "】卖出了一张票,现在剩余了【" + ticketNumber + "】张票");
ticketNumber--;
} else {
break;
}
}catch (Exception e){
e.printStackTrace();
}finally {//注意:要放到finally中
lock.unlock();//释放锁
}
}
}
}
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。
用关键字synchronized构成同步代码块和同步方法,来实现多线程的同步,本质上可以理解为底层的程序给线程加了一把看不见的隐藏的锁,只有获取到这把锁的线程才能被执行,没拿到的线程就得等着,从而控制线程的执行顺序,达到同步效果,所以,任何线程进入同步代码块、同步方法之前,必须先获得对于同步监测器的锁定,那么谁释放对同步监测器的锁定呢?
在Java中,程序无法显式的释放对同步监测器的锁定,释放权在底层的JVM上,JVM会从释放机制中自动的释放。