实现线程同步一个使synchronized关键字,一个是通过对象lock.
Lock 在jdk 1.5才出现的,在一定程度上缓解了synchronized同步所带来的性能下降。
Synchronized
synchronized时对象一定会被阻塞,其他线程必须等待锁释放后才能执行,在高并发的情况下,很容易降低性能,而且不容易控制会出现死锁。
原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。
Lock
需要显示指定起始位置和终止位置。一般使用ReentrantLock类做为锁,多个线程中必须要使用一个ReentrantLock类做为对象才能保证锁的生效。且在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。
lockk用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就是CAS操作(Compare and Swap).
public class LockTest {
public static void main(String[] args) {
final Outputter1 output = new Outputter1();
new Thread() {
public void run() {
output.output("zhangsan");
};
}.start();
new Thread() {
public void run() {
output.output("lisi");
};
}.start();
}
}
class Outputter1 {
private Lock lock = new ReentrantLock();// 锁对象
public void output(String name) {
// TODO 线程输出方法
lock.lock();// 得到锁
try {
for(int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
} finally {
lock.unlock();// 释放锁
}
}
}
Synchronized 和Lock
synchronized 要比lock同步的性能消耗高,而lock比synchronized优越就优越在的java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,这样就可以基于lock实现不同的调用算法、性能特性或者锁定语义。
我们之前说synchronized在多线程竞争激烈的时候可能会出现性能极速下降的问题。ReentrantLock在多线程抢占资源的时候可以保障当许多线程都想访问共享资源时,JVM 可以花更少的时候来调度线程,把更多时间用在执行线程上。
利用ReentrantLock()来保护共享资源。
Lock lock = new ReentrantLock();
lock.lock();
try {
// update object state
}
finally {
lock.unlock();
}
ReentrantLock获得锁的方式
lock(),如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,知道获取锁
trylock(),如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false
trylock(),如果获取了锁立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待过程如果获得了锁,则返回true,如果等待超时,则返回false。
lockInterruptibly,如果截取了锁则立即返回,如果没有获取锁定,当前线程处于休眠状态,直到获得锁,或者是当前线程被别的线程中断。
我们看出使用ReentrantLock来实现同步相对于Synchronized更灵活,
一方面
在Synchronized中使用同步可能会出现等待持有对象锁的线程释放锁,但是如果这个线程的周期很长,在这个过程中等待中的线程可能会一直等待直到等死。这样就消耗了大量了系统资源。
另一方面出现死锁的可能性更大,线程A拿到锁,并且runing,而线程B等待A释放锁,如果A需要B中的资源,就陷入了无限等待的过程中了。
最后,在多线程共享资源时,减少了线程间切换所花费得资源,对CPU的利用率比较低。
ReentrantLock给了一种机制让我们来响应中断,可能自行中断,也可以被线性中断,是很灵活的。
应用场景:
lock支持的时间锁等候、可中断锁等候、无块结构锁、多个条件变量或者锁投票。
synchronized可以实现的功能,基本上lock都能实现。虽然看起来lock的出现似乎已经可以取代synchronized,但是synchronized似乎也有些优点,lock中的锁定类是用于高级用户和高级情况的工具,如果在没有特别的需求的情况下一般还是以使用synchronized为主,另外,lock需要程序员手动加锁和手动释放锁,而synchronized在退出 synchronized 块时JVM就能自动的释放锁。
参考链接:
http://blog.csdn.net/natian306/article/details/18504111
http://blog.csdn.net/fw0124/article/details/6672522