为什么java已经通过synchronized关键字实现同步访问了,还需要提供Lock?
synchronized的缺陷
前面博客有提到过释放对象的锁有两种情况:
程序执行完同步代码块会释放代码块。
程序在执行同步代码块是出现异常,JVM会自动释放锁去处理异常。
如果获取锁的线程需要等待I/O或者调用了sleep()方法被阻塞了,但仍持有锁,其他线程只能干巴巴的等着,这样就会很影响程序效率。
因此就需要一种机制,可以不让等待的线程已知等待下去,比如值等待一段时间或响应中断,Lock锁就可以办到。
再举个例子:当有多个线程读写文件时,读操作和写操作会发生冲突现象,写操作和写操作会发生冲突现象,但是读操作和读操作不会发生冲突现象。但是采用synchronized关键字来实现同步的话,就会导致一个问题:如果多个线程都只是进行读操作,所以当一个线程在进行读操作时,其他线程只能等待无法进行读操作。
因此就需要一种机制来使得多个线程都只是进行读操作时,线程之间不会发生冲突,通过Lock就可以办到。
另外,Lock可以知道线程有没有得到锁,而synchronized不能。
总结区别
总结来说,Lock与synchronized有以下区别:
- Lock是一个接口,而synchronized是关键字。
- synchronized会自动释放锁,而Lock必须手动释放锁。
- Lock可以让等待锁的线程响应中断,而synchronized不会,线程会一直等待下去。
- 通过Lock可以知道线程有没有拿到锁,而synchronized不能。
- Lock能提高多个线程读操作的效率。
- synchronized能锁住类、方法和代码块,而Lock是块范围内的