java.util.concurrent包下的都是线程安全的
synchronized关键字可以实现同步访问
还有 java.util.concurrent.locks 包下也提供了另一种方式实现同步访问
一、synchronized的缺陷
synchronized是java中的一个关键字 也就是说是Java语言内置的特性 那么为什么会出现Lock呢?
如果一个代码块被synchronized修饰了 当一个线程获取了对应的锁 并执行该代码块时 其他线程便只能一直等待
等待获取锁的线程释放锁 而这里获取锁的线程释放锁只会有两种情况:
1)获取锁的线程执行完了该代码块 然后线程释放对锁的占有
2)线程执行发生异常 此时JVM会让线程自动释放锁
那么如果这个获取锁的线程由于要等待IO或者其他原因(比如调用sleep方法)被阻塞了 但是又没有释放锁
其他线程便只能等待 这就会影响程序执行效率
因此就需要有一种机制可以不让等待的线程一直无期限地等待下去(比如只等待一定的时间或者能够响应中断)通过Lock就可以办到
再有 当有多个线程读写文件时 读操作和写操作会发生冲突现象 写操作和写操作会发生冲突现象 但是读操作和读操作不会发生冲突现象
但是采用synchronized关键字来实现同步的话 就会导致一个问题:
如果多个线程都只是进行读操作 所以当一个线程在进行读操作时 其他线程只能等待无法进行读操作
因此就需要一种机制来使得多个线程都只是进行读操作时 线程之间不会发生冲突 通过Lock也可以办到
另外 通过Lock可以知道线程有没有成功获取到锁 这个是synchronized无法办到的
总结 也就是说Lock提供了比synchronized更多的功能
但是要注意以下几点:
1)Lock不是Java语言内置的 synchronized是Java语言的关键字 因此是内置特性 Lock是一个接口 通过这个接口下的实现类可以实现同步访问
2)Lock和synchronized有一点非常大的不同
采用synchronized不需要用户去手动释放锁 当synchronized方法或者synchronized代码块执行完之后 系统会自动让线程释放对锁的占用
而Lock则必须要用户去手动释放锁 如果没有主动释放锁 就有可能导致出现死锁现象
3)synchronized是悲观锁 Lock是乐观锁
所以性能上来说 Lock性能更好
4)synchronized和lock其实底层都是CAS锁(CAS原子锁)
悲观锁都是乐观锁封装出来的
Java本身是无法实现原子锁的 只是因为Java调用了操作系统的接口
(原子锁是在硬件上实现的 Java是软件 原子锁是需要依赖操作系统和硬件的支持)
二、java.util.concurrent.locks包下常用的类
