自己动手写java锁
1、LockSupport的park和unpark方法的基本使用,以及对线程中断的响应性
LockSupport是JDK中比较底层的类,用来创建锁和其他同步工具类的基本线程阻塞原语。java锁和同步器框架的核心AQS:AbstractQueuedSynchronizer,就是通过调用LockSupport.park()和LockSupport.unpark()实现线程的阻塞和唤醒的。LockSupport很类似于二元信号量(只有1个许可证可供使用),如果这个许可还没有被占用,当前线程获取许可并继续执行;如果许可已经被占用,当前线程阻塞,等待获取许可。注意:许可默认是被占用的。
public static void main(String[] args) {
LockSupport.park();
System.out.println("block.");
}
运行该代码,可以发现主线程一直处于阻塞状态,不会输出block.。因为许可默认是被占用的,调用park()时获取不到许可,所以进入阻塞状态。需要注意的是,尝试获取许可证的是调用了 LockSupport.park()方法的线程。
LockSupport.unpark(Thread thread)方法需要传入一个线程作为参数,该方法的作用是允许作为参数的线程获取许可证,也就是唤醒作为参数的线程。public static void main(String[] args) {
Thread thread = Thread.currentThread();
LockSupport.unpark(thread);//释放许可
LockSupport.park();// 获取许可
System.out.println("b");
}
LockSupport是不可重入的,如果一个线程连续2次调用LockSupport.park(),那么该线程一定会一直阻塞下去。
public static void main(String[] args) throws Exception {
Thread thread = Thread.currentThread();
LockSupport.unpark(thread);
System.out.println("a");
LockSupport.park();
System.out.println("b");
LockSupport.park();
System.out.println("c");
}
这段代码打印出a和b,不会打印c,因为第二次调用park的时候,线程无法获取许可出现死锁。
1.1、LockSupport对中断的响应性
LockSupport.park()能响应中断,也就是说A线程调用了LockSupport.park()方法被阻塞后,其他线程调用了A线程的interrupt()方法给A线程发送中断信号时,A线程的阻塞状态会被中断,继续执行。当然了,调用了了某线程的interrupt()方法后,该线程的中断状态isInterrupted()会由false变为true。
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
private int count = 0;
@Override
public void run() {
long start = System.currentTimeMillis();
long end = 0;
while ((end - start) <= 1000) {
count++;
end = System.currentTimeMillis();
}
System.out.println("after 1 second.count=" + count);
System.out.println("thread " + Thread.currentThread().isInterrupted());
//等待或许许可
LockSupport.park();
System.out.println("thread over." + Thread.currentThread().isInterrupted());
}
});
t.start();
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("向调用LockSupport.park()方法被阻塞的线程发送中断信号");
// 中断线程
t.interrupt();
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main over");
}
最终线程会打印出thread over.true。这说明线程如果因为调用LockSupport.park()而阻塞的话,能够响应中断请求(中断状态被设置成true),但是不会抛出InterruptedException。
2、Thread详解
isInterrupted() 只获取线程的中断状态,返回值为线程的中断状态(每个线程都有一个中断状态标志位,用于表明当前线程是否处于中断状态)
interrupted() 获取线程的中断状态,并清空状态(即如果线程的中断状态为true,则将其设置为false;如果线程的中断状态为false,则什么也不做),返回值为清空状态前线程的中断状态
一般调用Thread的interrupt()会有两种处理方式:
(1)遇到一个低优先级的block状态时,比如object.wait(),object.sleep(),object.join()导致线程阻塞,它会立马触发一个unblock解除阻塞,并在线程阻塞的位置抛出一个InterruptedException,此时当前线程的中断状态标志为false
(2)其他情况导致的线程阻塞,Thread的interrupt()仅仅是更新了线程的中断状态标志位。然后线程继续执行,当然你也可以通过Thread.isInterrrupted()进行检查,做相应的处理,比如也抛出InterruptedException或者是清理状态,取消task等。
自己动手写java锁的更多相关文章
- 死磕 java同步系列之自己动手写一个锁Lock
问题 (1)自己动手写一个锁需要哪些知识? (2)自己动手写一个锁到底有多简单? (3)自己能不能写出来一个完美的锁? 简介 本篇文章的目标一是自己动手写一个锁,这个锁的功能很简单,能进行正常的加锁. ...
- 自己动手写把”锁”---LockSupport介绍
本篇是<自己动手写把"锁">系列技术铺垫的最后一个知识点.本篇主要讲解LockSupport工具类,它用来实现线程的挂起和唤醒. LockSupport是Java6引入 ...
- 自己动手写把”锁”---LockSupport深入浅出
本篇是<自己动手写把"锁">系列技术铺垫的最后一个知识点.本篇主要讲解LockSupport工具类,它用来实现线程的挂起和唤醒. LockSupport是Java6引入 ...
- 自己动手写Java大整数《3》除法和十进制转换
之前已经完毕了大整数的表示.绝对值的比較大小.取负值.加减法运算以及乘法运算. 详细见前两篇博客(自己动手写Java * ). 这里加入除法运算. 另外看到作者Pauls Gedanken在blog( ...
- [JVM] - 一份<自己动手写Java虚拟机>的测试版
go语言下载 配置GOROOT(一般是自动的),配置GOPATH(如果想自己改的话) 参照<自己动手写Java虚拟机> > 第一章 指令集和解释器 生成了ch01.exe文件 这里还 ...
- 自己动手写java 字节流输入输出流
数据流是一串连续不断的数据的集合,就象水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流. "流是磁盘或其它外围设备中存储的数据的源点或终点." ...
- 自己动手写把”锁”之---JMM和volatile
一.JAVA内存模型 关于Java内存模型的文章,网上真的数不胜数.在这里我就不打算说的很详细.很严谨了.只力求大家能更好的理解和运用,为后边的技术点做铺垫. 内存模型并不是Java独有的概念,而 ...
- Java并发编程:自己动手写一把可重入锁
关于线程安全的例子,我前面的文章Java并发编程:线程安全和ThreadLocal里面提到了,简而言之就是多个线程在同时访问或修改公共资源的时候,由于不同线程抢占公共资源而导致的结果不确定性,就是在并 ...
- Java自己动手写连接池四
Java自己动手写连接池四 测试: package com.kama.cn; import java.sql.Connection; public class Test { public static ...
随机推荐
- centos7.4中安装docker
#!/bin/sh # 安装docker # 在docker中安装mysql # 解决了docker容器中无法输入中文的问题 ##########################安装docker # ...
- Windows server 服务器的端口突然远程连不上了,但是可以远程连接,怎么回事?
①:先ping一下,查看网络是否正常:正常的话.telnet IP 端口,查看端口是否开启了. 可以ping,不能telnet就可能是做了端口限制,可以参考以下的步骤: ②:若是不能ping,则可能是 ...
- __x__(40)0909第五天__表格 table 的 css 样式 美化
如果就向下面的代码那样,不写 tbody , 则浏览器自添加 tbody , 并将所有的 tr 移入 tbody 意味着 tr 并非 table 的子元素,而是 tbody 的子元素. 所以 以后编写 ...
- vue菜鸟从业记:公司项目里如何进行前后端接口联调
最近我的朋友王小闰进入一家新的公司,正好公司项目采用的是前后端分离架构,技术栈是王小闰非常熟悉的vue全家桶,后端用的是Java语言. 在前后端开发人员碰面之后,协商确定好了前端需要的数据接口(扯那么 ...
- 推荐几种Java任务调度的实现
几种任务调度的 Java 实现方法与比较--转载 原文:http://www.ibm.com/developerworks/cn/java/j-lo-taskschedule/ 写了一天的作业调度,这 ...
- C语言复习0_准备工作
前言: 第一次接触C语言是大一下学期的时候,2013年上半年,那个时候的开发工具还是VS C++,今天了解了一下,常用的开发工具变成了CodeBlocks.决定趁着毕业到入职这一段CD时间,拾起这门语 ...
- 外网访问VMware虚拟机
目的: 主机上安装了VMware,VMware上安装了Linux虚拟机(我安装的是Centos7).我想让虚拟机向外提供Web服务.本文记录如何让我的主机和外网用户可以访问VM虚拟机上的Web. ...
- 火狐浏览器安装firebug和firepath插件方法(离线)
1.下载FF55以内版本安装包,安装后在Firefox 更新选择"不检查更新" 2.火狐浏览器各个版本下载地址:http://ftp.mozilla.org/pub/firefox ...
- C#的托管与非托管大难点
托管代码与非托管代码 众所周知,我们正常编程所用的高级语言,是无法被计算机识别的.需要先将高级语言翻译为机器语言,才能被机器理解和运行.在标准C/C++中,编译过程是这样的:源代码首先经过预处理器,对 ...
- Win10安装和配置JDK
方法/步骤 1.JDK下载 JDK下载可以在官网下载,如图所示,但由于是国外网站,往往下载速度比较慢,所以推荐在百度软件中心下载.这里要注意自己电脑是32位还是64位,根据具体情况下载相应安装包. ...