简述synchronized和java.util.concurrent.locks.Lock的异同
2016-06-14 00:00
507 查看
简述synchronized和java.util.concurrent.locks.Lock的异同
源码来自一篇Java基础题
主要相同点:Lock能完成synchronized所实现的所有功能
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放(因为如果不在finally中释放的情况,当抛出异常时,线程直接死掉,但是没有释放锁,使得其他相关线程无法执行。读者可以试试在定义一个数组,并访问越界区,使得程序抛出异常,但是释放锁并未在finally中)。
源码例子:
Java代码
package test.thread;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
private int j;
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
TestLock tt = new TestLock();
for (int i = 0; i < 2; i++) {
new Thread(tt.new Adder()).start();
new Thread(tt.new Subtractor()).start();
}
}
private class Subtractor implements Runnable {
@Override
public void run() {
for (int i = 0; i < 15; i++) {
// 这里抛异常了,锁能释放吗?会释放,但是lock就不会释放,所以需要加上try..catch
/*synchronized (TestLock.this) {
System.out.println("j--=" +j--);
}*/
lock.lock();
try {
System.out.println("j--=" + j--);
} finally {
lock.unlock();
}
}
}
}
private class Adder implements Runnable {
@Override
public void run() {
for (int i = 0; i < 15; i++) {
/*synchronized (TestLock.this) {
System.out.println("j++="+j++);
}*/
lock.lock();
try {
System.out.println("j++=" + j++);
} finally {
lock.unlock();
}
}
}
}
}
Lock还有更强大的功能,例如,它的tryLock方法可以非阻塞方式去拿锁。
tryLock()
tryLock(long timeout, TimeUnit timeUnit)
trylock()方法:如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false;
tryLock(long timeout, TimeUnit timeUnit)方法:如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false;
是不是比synchronized灵活就体现出来了,比如:你现在正在忙于工作,突然感觉内急,于是你跑向洗手间,到门口发现一个“清洁中,暂停使用”的牌牌。没办法,工作又忙,所以你只好先放弃去洗手间回去忙工作,可能如此反复,终于你发现可以进了,于是......
如果用synchronized,当你发现洗手间无法暂时无法进入时,就只能乖乖在门口干等了。
而使用trylock()呢,首先你试着去洗手间,发现暂时无法进入(trylock返回false),于是你继续忙你的工作,如此反复,直到可以进入洗手间为止(trylock返回true)。甚至,你非常急,你可以尝试性的在门口等20秒,不行再去忙工作(trylock(20, TimeUnit.SECONDS);)。
源码来自一篇Java基础题
主要相同点:Lock能完成synchronized所实现的所有功能
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放(因为如果不在finally中释放的情况,当抛出异常时,线程直接死掉,但是没有释放锁,使得其他相关线程无法执行。读者可以试试在定义一个数组,并访问越界区,使得程序抛出异常,但是释放锁并未在finally中)。
源码例子:
Java代码
package test.thread;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
private int j;
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
TestLock tt = new TestLock();
for (int i = 0; i < 2; i++) {
new Thread(tt.new Adder()).start();
new Thread(tt.new Subtractor()).start();
}
}
private class Subtractor implements Runnable {
@Override
public void run() {
for (int i = 0; i < 15; i++) {
// 这里抛异常了,锁能释放吗?会释放,但是lock就不会释放,所以需要加上try..catch
/*synchronized (TestLock.this) {
System.out.println("j--=" +j--);
}*/
lock.lock();
try {
System.out.println("j--=" + j--);
} finally {
lock.unlock();
}
}
}
}
private class Adder implements Runnable {
@Override
public void run() {
for (int i = 0; i < 15; i++) {
/*synchronized (TestLock.this) {
System.out.println("j++="+j++);
}*/
lock.lock();
try {
System.out.println("j++=" + j++);
} finally {
lock.unlock();
}
}
}
}
}
Lock还有更强大的功能,例如,它的tryLock方法可以非阻塞方式去拿锁。
tryLock()
tryLock(long timeout, TimeUnit timeUnit)
trylock()方法:如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false;
tryLock(long timeout, TimeUnit timeUnit)方法:如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false;
是不是比synchronized灵活就体现出来了,比如:你现在正在忙于工作,突然感觉内急,于是你跑向洗手间,到门口发现一个“清洁中,暂停使用”的牌牌。没办法,工作又忙,所以你只好先放弃去洗手间回去忙工作,可能如此反复,终于你发现可以进了,于是......
如果用synchronized,当你发现洗手间无法暂时无法进入时,就只能乖乖在门口干等了。
而使用trylock()呢,首先你试着去洗手间,发现暂时无法进入(trylock返回false),于是你继续忙你的工作,如此反复,直到可以进入洗手间为止(trylock返回true)。甚至,你非常急,你可以尝试性的在门口等20秒,不行再去忙工作(trylock(20, TimeUnit.SECONDS);)。
相关文章推荐
- 聊聊并发(七)——Java中的阻塞队列
- eclipse java debug 日志输出到文件里面
- java.sql.SQLException: Fail to convert to internal
- java中的匿名内部类总结
- SpringMVC的运行流程图
- Spring线程池与JDK线程池配置
- Java实现的二分查找算法
- 一个例子说明java局部代码块、静态代码块、构造代码块区别
- java System.exit(int status)使用
- 【译】Java中的对象序列化
- Java里面关于currentTimeMilllis()方法
- Java性能优化权威指南-读书笔记(二)-JVM性能调优-概述
- spring+mybatis学习之路之错误笔记day05
- java通过Solr的Suggest实现提示词
- Java通过WebSocket WebRTC实现视频通话实例
- Java 继承Thread类和实现Runnable接口的区别
- Java 继承Thread类和实现Runnable接口的区别
- Java 继承Thread类和实现Runnable接口的区别
- 十分钟理解 Java 中的动态代理
- 关于java中类型参数的通配符总结