public interface MyLock {

    void lock () throws InterruptedException;

    void lock(long millis) throws TimeoutException , InterruptedException ,ParametersIllegalException;

    void unlock();

    class TimeoutException  extends Exception{

        TimeoutException(String msg){
super(msg);
}
private static final long serialVersionUID = 1L;
} class ParametersIllegalException extends Exception{ ParametersIllegalException(String msg){
super(msg);
}
private static final long serialVersionUID = 1L;
}
}
public class MyLockImpl  implements MyLock{

    private boolean  initValue; // false表示monitor没有被占用

    private Thread currentThread;

    @Override
public synchronized void lock() throws InterruptedException {
while(initValue) {//monitor被占用
this.wait();
}
initValue = true;
currentThread = Thread.currentThread();
} @Override
public synchronized void unlock() {
if(currentThread == Thread.currentThread()) {
System.out.println("【"+Thread.currentThread().getName()+"】" + " release the monitor");
initValue = false;
this.notifyAll();
}
} @Override
public synchronized void lock(long millis) throws TimeoutException, InterruptedException, ParametersIllegalException {
if (millis <= )
throw new ParametersIllegalException("parameters illegal");
long hasRemaining = millis;
long endTime = System.currentTimeMillis() + millis;
while (initValue) {
if (hasRemaining <= )
throw new TimeoutException("Time out");
this.wait(millis);
hasRemaining = endTime - System.currentTimeMillis();
}
this.initValue = true;
this.currentThread = Thread.currentThread();
} }
public class MyLockTest {

    public static void main(String[] args) {
MyLock myLock = new MyLockImpl(); Stream.of("T1","T2","T3","T4").forEach(name ->
new Thread(()-> {
try {
myLock.lock();
System.out.println("【"+Thread.currentThread().getName()+"】" +" get the monitor");
m1();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (TimeoutException e) {
System.out.println("【"+Thread.currentThread().getName()+"】" +" timeout");
} catch (ParametersIllegalException e) {
System.out.println("【"+Thread.currentThread().getName()+"】" +" parameter illegal");
//e.printStackTrace();
}finally {
myLock.unlock();
}
},name).start()
);
} public static void m1() throws InterruptedException {
System.out.println("【"+Thread.currentThread().getName()+"】" + "is working ...");
Thread.sleep(3_000);
} }

注意wait方法可能存在spurious(假的)唤醒,wait方法应该在一个循环中使用

采用synchronized关键字写一个显示锁的更多相关文章

  1. 使用semaphore写一个显示锁

    /** * 这里只是将Semaphore包装了一下,注意当Semaphore的构造参数是1时,本身就是一个显示锁 */ public class SemaphoreLock { ); public v ...

  2. 使用AtomicInteger写一个显示锁

    利用了AtomicInteger的compareAndSet方法 public class CASLock { private AtomicInteger value = new AtomicInte ...

  3. 如何使用Shell写一个显示目录结构的命令?

    公众号关注 「开源Linux」 回复「学习」,有我为您特别筛选的学习资料~ 在Linux中使用Shell写一个显示目录结构的命令,快速寻找目录结构. 1.代码 #!/usr/bin/env bash ...

  4. Java:synchronized关键字引出的多种锁

    前言 Java 中的 synchronized关键字可以在多线程环境下用来作为线程安全的同步锁.本文不讨论 synchronized 的具体使用,而是研究下synchronized底层的锁机制,以及这 ...

  5. 用javascript写一个显示时间差 几分钟前 几小时前 几天前 几周前 大于一个月显示日期

    window.onload = function(){ var show_times = $(".times span"); for(var i=0;i<show_times ...

  6. JAVA多线程之Synchronized关键字--对象锁的特点

    一,介绍 本文介绍JAVA多线程中的synchronized关键字作为对象锁的一些知识点. 所谓对象锁,就是就是synchronized 给某个对象 加锁.关于 对象锁 可参考:这篇文章 二,分析 s ...

  7. java线程总结--synchronized关键字,原理以及相关的锁

    在多线程编程中,synchronized关键字非常常见,当我们需要进行“同步”操作时,我们很多时候需要该该关键字对代码块或者方法进行锁定.被synchronized锁定的代码块,只能同时有一条线程访问 ...

  8. 精通java并发-synchronized关键字和锁

    目前CSDN,博客园,简书同步发表中,更多精彩欢迎访问我的gitee pages synchronized关键字和锁 示例代码 public class MyThreadTest2 { public ...

  9. Java多线程:synchronized关键字和Lock

    一.synchronized synchronized关键字可以用于声明方法,也可以用来声明代码块,下面分别看一下具体的场景(摘抄自<大型网站系统与Java中间件实践>) 案例一:其中fo ...

随机推荐

  1. javascript深入理解js闭包(转载)

    此篇文章来源于http://www.jb51.net/article/24101.htm 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全 ...

  2. 《HelloGitHub月刊》第 11 期

    <HelloGitHub>第 11 期 兴趣是最好的老师,<HelloGitHub>就是帮你找到兴趣! 简介 最开始我只是想把自己在浏览 GitHub 过程中,发现的有意思.高 ...

  3. List-ArrayList集合基础增强底层源码分析

    List集合基础增强底层源码分析 作者:Stanley 罗昊 [转载请注明出处和署名,谢谢!] 集合分为三个系列,分别为:List.set.map List系列 特点:元素有序可重复 有序指的是元素的 ...

  4. opensuse使用zypper安装软件

    安装软件(opensuse) opensuse 通过zypper可以方便的进行软件管理,类似centos的yum 软件. 命令参考 软件包操作 搜索软件 zypper search package 安 ...

  5. Docker系列05—Docker 存储卷详解

    本文收录在容器技术学习系列文章总目录 1.存储卷介绍 1.1 背景 (1)docker 的 AFUS 分层文件系统 docker镜像由多个只读层叠加面成,启动容器时,docker会加载只读镜像层并在镜 ...

  6. Linux之数据库操作

    一.mysql基本操作 ,连接数据库 mysql -u root -p -h 127.0.0.1 mysql -u root -p -h 192.168.12.56 ,授予远程连接的权限 grant ...

  7. Lily_music 网页音乐播放器 -可搜索(附歌词联动播放效果解说)

    博客地址:https://ainyi.com/59 写在前面 这是我今年(2018)年初的小项目,当时也是手贱,不想用别的播放器,想着做一个自己的网页播放器,有个歌曲列表.可关键词搜索.歌词滚动播放的 ...

  8. 一统江湖的大前端(2)—— Mock.js + Node.js 如何与后端潇洒分手

    <一统江湖的大前端>系列是自己的前端学习笔记,旨在介绍javascript在非网页开发领域的应用案例和发现各类好玩的js库,不定期更新.如果你对前端的理解还是写写页面绑绑事件,那你真的是有 ...

  9. 重写(override)和重载(overload)的区别

    override(重写): 是进行基类中函数的重写,是面向对象的概念 重载(overload):是方法的名称相同,参数或参数类型不同,进行多次重载以适应不同的需要.overload 是面向对象的概念.

  10. Fundebug后端Java异常监控插件更新至0.3.1,修复Maven下载失败的问题

    摘要: 0.3.1修复Maven下载失败的问题. 监控Java应用 1. pom.xml 配置fundebug-java依赖 <dependency> <groupId>com ...