使用synchronized 实现ReentrantLock(美团面试题目)
刚看到这个题目的时候无从下手,因为觉得synchronized和lock在加锁的方式上有很大不同,比如,看看正常情况下synchronized时如何加锁的。
方式一:
public synchronized void a(){
//TODO
}
方式二:
public void b(){
synchronized(this){
//TODO
}
}
从这两种方式来看,锁都是加在{}之间的,我们再来看看Lock是如何做的呢:
public void c() {
lock.lock();
try {
// TODO
} finally {
lock.unlock();
}
}
这种方式的锁是加在lock() 和unlock()之间的,所以要想实现一个lock功能,就要想怎么实现这样两个方法,lock()和unlock()方法,先定义一个框架如下所示:
public void lock(){
}
public void unlock(){
}
然后要想怎么用synchronized去实现这两个方法。
现在其实只是稍微清楚了一点思路,但是还不知道怎么去填充这两个方法,这是后再来分析一下Lock的加锁有什么特点,再来看看这段代码:
public void c() {
lock.lock();//When current thread get the lock, other thread has to wait
try {
//current thread get in the lock, other thread can not get in
// TODO
} finally {
lock.unlock();//current thread release the lock
}
}
这段代码我只是加了一点注释,别的什么都没有做,是不是帮助理解这段代码,看看出现频率最高的词是什么,是current thread,那么我们去填充lock()和unlock()方法的时候是不是注意要抓住current thread这个关键字就可以找到解决方案呢?答案是肯定的。
接着分析,使用synchronized的时候如何让线程等待呢?是用wait()方法。怎么让线程唤醒呢,是用notify()方法。那么就要在lock()方法中使用wait()方法,在unlock()方法中使用notify()方法。那么我们在使用wait()和notify()的时候是有一个条件的,想想我们应该使用什么作为条件呢?
我们应该使用当前锁是否被占用作为判断条件,如果锁被占用,current thread等待,想想我们在使用synchronized的时候是不是一直使用的这个条件,答案也是肯定的。
再来分析一下什么时候释放锁,使用什么作为条件,想想如果线程A拿到了锁,线程B能释放吗?当然不能,如果B能释放就违反了原则,当然不能。肯定是A线程的锁只能A来释放。所以判断条件就是判断持有锁的线程是不是current thread,如果是的话,可以释放,不是的话当然不能。
现在来看看完整的代码:网上写的有点乱,我自己从新整理了一下,并且可以正常运行
package test_lock; import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory; public class NaiveLock { private static final long NONE=-1;
private long owner =NONE; public synchronized void lock(){
long currentThreadId=Thread.currentThread().getId();
if(owner==currentThreadId){
throw new IllegalStateException("lock has been acquired by current thread");
} while(this.owner!=NONE){ System.out.println(String.format("thread %s is waiting lock", currentThreadId));
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.owner=currentThreadId;
System.out.println(String.format("lock is acquired by thread %s", currentThreadId)); } public synchronized void unlock(){ long currentThreadId=Thread.currentThread().getId(); if(this.owner!=currentThreadId){
throw new IllegalStateException("Only lock owner can unlock the lock");
} System.out.println(String.format("thread %s is unlocking", owner));
owner=NONE;
notify(); } public static void main(String[] args) {
// TODO Auto-generated method stub
final NaiveLock lock=new NaiveLock();
ExecutorService executor= Executors.newFixedThreadPool(20, new ThreadFactory(){
private ThreadGroup group =new ThreadGroup("test thread group");
{
group.setDaemon(true);
}
@Override
public Thread newThread(Runnable r) {
// TODO Auto-generated method stub
return new Thread(group,r);
}}); for(int i=0;i<20;i++){
executor.submit(new Runnable(){ @Override
public void run() {
// TODO Auto-generated method stub
lock.lock();
System.out.println(String.format("thread %s is running...", Thread.currentThread().getId())); try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lock.unlock();
}});
} } }
结果为:
lock is acquired by thread 10
thread 10 is running...
thread 29 is waiting lock
....
thread 13 is running...
thread 13 is unlocking
lock is acquired by thread 12
thread 12 is running...
thread 12 is unlocking
使用synchronized 实现ReentrantLock(美团面试题目)的更多相关文章
- Java 常用数据结构对象的实现原理 集合类 List Set Map 哪些线程安全 (美团面试题目)
Java中的集合包括三大类,它们是Set.List和Map, 它们都处于java.util包中,Set.List和Map都是接口,它们有各自的实现类. List.Set都继承自Collection接口 ...
- 如何用grep命令同时显示匹配行上下的n行 (美团面试题目)
标准unix/linux下的grep通过以下参数控制上下文 grep -C 5 foo file 显示file文件中匹配foo字串那行以及上下5行grep -B 5 foo file 显示foo及前5 ...
- 面试突击42:synchronized和ReentrantLock有什么区别?
在 Java 中,常用的锁有两种:synchronized(内置锁)和 ReentrantLock(可重入锁),二者的功效都是相同得,但又有很多不同点,所以我们今天就来聊聊. 区别1:用法不同 syn ...
- java 美团面试常见问题总
一 基础篇 1. System.out.println(3|9)输出什么? 2. 说一下转发(Forward)和重定向(Redirect)的区别 3. 在浏览器中输入url地址到显示主页的过程,整个过 ...
- java 面试题目(java高级架构)
题目信息 java基础: 1. Java 基础 JDK 和 JRE 有什么区别? Java中JDK和JRE的区别是什么?它们的作用分别是什么? == 和 equals 的区别是什么? 两个对象的 ...
- 线程安全之 synchronized 和 ReentrantLock
线程安全之 synchronized 和 ReentrantLock + 面试题 前面我们介绍了很多关于多线程的内容,在多线程中有一个很重要的课题需要我们攻克,那就是线程安全问题.线程安全问题指的是在 ...
- (转)喜马拉雅2018 Java面试题目
背景:将网上的题目整理下. java基础 1:hashTable hashMap ConcurrentHashMap 的区别.数据结构.线程安全 2:equals和==区别, 重写equals一定要重 ...
- Synchronized 与 ReentrantLock 的区别!
来源:cnblogs.com/baizhanshi/p/7211802.html 之前栈长分享了重入锁的概念:<到底什么是重入锁,拜托,一次搞清楚!>,今天现来深入了解下 Synchron ...
- 全网最全C#实习面试题目
整个内容是我在春招面试时候整理的一些题目,里面涵盖有网上搬运的(由于当时没有记录来源,如果有转载没标注来源,请与我联系),还有我面试到的.整个排版很乱,后期我会一步一步整理.整个内容大概快有两万字.整 ...
随机推荐
- (5)HomeAssistant mqtt-433-esp8266-arduino-传感器
Home Assistant Integrations使用 https://github.com/1technophile/OpenMQTTGateway/wiki/Home-assistant-in ...
- pytorch学习-AUTOGRAD: AUTOMATIC DIFFERENTIATION自动微分
参考:https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html#sphx-glr-beginner-blitz-autog ...
- 箱线图boxplot
箱线图boxplot--展示数据的分布 图表作用: 1.反映一组数据的分布特征,如:分布是否对称,是否存在离群点 2.对多组数据的分布特征进行比较 3.如果只有一个定量变量,很少用箱线图去看数据的分布 ...
- 为什么我的mac插入耳机耳机没有声音呢?
macOS 系统莫名其妙就遇到声音和音频播放问题的情况相当普遍,在新添音频设备.应用程序之间进行切换或更新操作系统后,都可能会遇到音频错误.好加在,解决大多数 macOS 声音无法正常工作的方法都非常 ...
- 开源版本PowerShell Core 6.2 发布
导读 PowerShell Core 6.2 GA 已发布,PowerShell Core 是 PowerShell 的开源版本,适用于 Linux,macOS 和 Windows. 有关 Power ...
- 在Python程序中的进程操作,multiprocess.Process模块
在python程序中的进程操作 之前我们已经了解了很多进程相关的理论知识,了解进程是什么应该不再困难了,刚刚我们已经了解了,运行中的程序就是一个进程.所有的进程都是通过它的父进程来创建的.因此,运行起 ...
- object detection[YOLOv2]
接着扯YOLO v2 相比较于YOLO v1,作者在之前模型上,先修修补补了一番,提出了YOLO v2模型.并基于imagenet的分类数据集和coco的对象检测数据集,提出了wordnet模型,并成 ...
- 一篇自己都看不懂的点分治&点分树学习笔记
淀粉质点分治可真是个好东西 Part A.点分治 众所周知,树上分治算法有$3$种:点分治.边分治.链分治(最后一个似乎就是树链剖分),它们名字的不同是由于分治方式的不同的.点分治,顾名思义,每一次选 ...
- Quartz.NET 任务调度教程。
https://www.cnblogs.com/yaopengfei/p/9216229.html
- 【IE11请求中止】 XMLHttpRequest: 网络错误 0x2ef3的意外出现
BUG现象 今天排查BUG遇到一个有趣的BUG,测试的截图显示 这个BUG只在IE11下出现. BUG原因 这个问题的原因是keep-alive机制引起. 当浏览器在向一个网址发起请求时,会建立一个t ...