- Lock可以使用 Condition 进行线程之间的调度
Synchronized 则使用 Object 对象本身的 notify,wait,notifyAll 调度机制
Condition 是 Java5 以后出现的机制,它有更好的灵活性,而且在一个对象里面可以有多个 condition,则线程可以注册在不同的 Condition,从而可以有选择性的调度线程,更加灵活。Synchronized 就相当于整个对象只有一个单一的 Condition 所有线程都注册在它身上,线程调度的时候之后调度所有的注册线程,没有选择权,会出现相当大的问题
Lock 的锁定是通过代码实现的,而 Synchronized 是在 JVM 层面上实现。synchronized 在锁定时如果方法块抛出异常,JVM 会将锁自动释放掉,不会因为出了异常没有释放造成线程死锁。但是 Lock 的话就享受不到 JVM 带来的自动功能,出现异常时必须在 finally 将锁释放掉,否则会引起死锁。
synchronized 的局限性:Lock 提供一种显式的,可轮询的定时的以及可中断的锁获取操作,synchronized是无法中断一个正在等待获得锁的线程,使用 synchronized 的线程在等待锁时是不能响应中断的
轮询锁:当不能同时获得所有的锁时,可以使用轮询锁或者定时锁避免死锁。当一个线程需要获取多个锁时,已获得一部分锁,但是另一部分不可得,此时会返回失败,释放已得锁,重新尝试获取所有的锁
总之,如果这个获取锁的线程由于要等待 IO 或者其他原因(比如调用 sleep,sleep 会使线程释放 cpu,但不会释放锁)被阻塞了,但是又没有释放锁,其他线程便只能干巴巴的等待,试想一下,这多么影响程序效率。因此就需要有一种机制可以不让等待的线程一直无期限地等待下去(比如只等待一定的时间或者能够响应中断),通过 Lock 就可以办到。再举个例子:当有多个线程读写文件时,读操作和写操作会发生冲突现象,写操作和写操作会发生冲突现象,但是读操作和读操作不会发生冲突现象(共享锁)。但是采用 synchronized 关键字实现同步的话,就会出现问题
如果多个线程都只是进行读操作,所以当一个线程在进行读操作时,其他线程只能等待无法进行读操作。因此就需要一种机制来使得多个线程都只是进行读操作,线程之间不会发生冲突,通过 Lock 就可以办到。另外,通过 Lock 可以让线程有没有成功获取到锁,这个是 synchronized 无法办到的。
共享锁参考:https://blog.csdn.net/u010577768/article/details/79995811