线程同步:1、
synchronized
关键字同步方法
2、
synchronized关键字同步代码块
3、
使用重入锁(ReentrantLock)实现线程同步
重入性:是指同一个线程多次试图获取它占有的锁,请求会成功,当释放锁的时候,直到重入次数为0,锁才释放完毕。
ReentrantLock是
接口Lock
的一个具体实现类,和synchronized关键字具有相同的功能,并具有更高级的一些功能。使用ReentrantLock时,
lock()和unlock()需要成对出现,否则会出现死锁,一般unlock都是放在finally中执行
。
synchronized和ReentrantLock的区别和使用选择:
1、使用synchronized获得的锁存在一定
缺陷
:
>不能中断一个正在试图获得锁的线程
>试图获得锁时不能像ReentrantLock中的trylock那样设定超时时间 ,当一个线程获得了对象锁后,其他线程访问这个同步方法时,必须等待或阻塞,如果那个线程发生了死循环,对象锁就永远不会释放;
> 每个锁只有单一的条件,不像condition那样可以设置多个
2、尽管synchronized存在上述的一些缺陷,在
选择上还是以synchronized优先
:
>
如果synchronized关键字适合程序,尽量使用它,可以
减少代码出错的几率
和
代码数量
;(减少出错几率是因为在执行完synchronized包含完的最后一句语句后,锁会自动释放,不需要像ReentrantLock一样手动写unlock方法;)
>如果特别需要Lock/Condition结构提供的独有特性时,才使用他们 ;(比如设定一个线程长时间不能获取锁时设定超时时间或自我中断等功能。)
>许多情况下可以使用java.util.concurrent包中的一种机制,它会为你处理所有的加锁情况;(比如当我们在多线程环境下使用HashMap时,可以使用ConcurrentHashMap来处理多线程并发)。