JAVA 锁
JAVA 锁
锁的概念
Java中的锁是控制资源访问的一种方式。它弥补了synchronized的可操作性不强的不足。
Java的锁都实现了Lock接口。Lock结构定义了锁的基本操作。
| 函数 | 解释 |
|---|---|
| void lock() | 获取锁,如果锁被其他线程占用,则等待 |
| void lockInterruptibly() throws InterruptedException | 获取锁,如果锁被其他线程占用,则等待。当该线程处于等待状态的时候,可以被interrupt()中断 |
| boolean tryLock() | 尝试获取锁,如果成功,返回true,如果失败,返回false |
| boolean tryLock(long time, TimeUnit unit) throws InterruptedException; | 与tryLock的不同是,使用该方法,如果无法获取锁,会等待一段时间,在这段时间内,如果无法获取,则返回false。 |
| Condition newCondition() | 与wait,notify 类似,必须和锁一起配合使用 |
lock的基本用法:
Lock lock = new ***();
lock.lock();
try {
//业务逻辑
} finally {
lock.unlock();
}
tryLock 的基本用法:
Lock lock = ***;
if(lock.tryLock()) {
try{
//处理业务
}catch(Exception ex){
}finally{
lock.unlock();
}
}else {
//获取不到锁,做其他业务
}
lockInterruptibly 的基本用法:
https://www.zhihu.com/question/36771163
package com.thread;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestLockInterruptibly
{
// @Test
public void test3() throws Exception
{
final Lock lock = new ReentrantLock();
lock.lock();
Thread t1 = new Thread(new Runnable()
{
@Override
public void run()
{
try
{
lock.lockInterruptibly();
}
catch(InterruptedException e)
{
System.out.println(Thread.currentThread().getName() + " interrupted.");
}
}
}, "child thread -1");
t1.start();
Thread.sleep(1000);
t1.interrupt();
Thread.sleep(1100);
}
public static void main(String[] args) throws Exception
{
new TestLockInterruptibly().test3();
}
}
上面是Lock接口的基本介绍,在实际使用中,主要有一下几种锁:
- 重入锁
- 读写锁
这些锁实现了Lock接口,为用户提供了统一的调用方法。内部实现基本都是通过聚合了一个队列同步器AbstractQueuedSynchronizer的子类来完成线程访问控制的。
ReentrantLock
ReentrantLock是一个重入锁,它表示该锁能够支持一个线程对资源的重复加锁。ReentrantLock还支持公平和非公平。
package com.thread;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class FairAndUnfairTest {
private static Lock fairLock = new ReentrantLock2(true);
private static Lock unfairLock = new ReentrantLock2(false);
public void fair() {
testLock(fairLock);
}
public void unfair() {
testLock(unfairLock);
}
public void testLock(Lock lock) {
for (int i = 0 ; i < 5; i++) {
Job job = new Job(lock);
job.start();
}
}
private static class Job extends Thread {
private Lock lock;
public Job(Lock lock) {
this.lock = lock;
}
public void run() {
lock.lock();
try {
System.out.print("current thread name is: " + this.getName());
print_list(lock);
} finally {
lock.unlock();
}
lock.lock();
try {
System.out.print("current thread name is: " + this.getName());
print_list(lock);
} finally {
lock.unlock();
}
}
private void print_list(Lock lock) {
ReentrantLock2 t_lock = (ReentrantLock2)lock;
Collection<Thread> threads = t_lock.getQueuedThreads();
System.out.print(" the thread in queue is : ");
for (Thread t : threads) {
System.out.print(t.getName() + ' ');
}
System.out.print('\n');
}
}
private static class ReentrantLock2 extends ReentrantLock {
public ReentrantLock2(boolean fair) {
super(fair);
}
public Collection<Thread> getQueuedThreads() {
List<Thread> arrayList = new ArrayList<Thread>(super.getQueuedThreads());
Collections.reverse(arrayList);
return arrayList;
}
}
public static void main(String[] args) {
FairAndUnfairTest test = new FairAndUnfairTest();
test.unfair();
}
}
ReentrantLock通过在构造函数中传入true和false设置为公平或者非公平。如果是公平锁,就会每次从等待队列中获取最前的线程使用锁,否则就当前线程很可能再次获得锁。
公平锁有助于平均分配资源,但是线程不断切换会造成更多的开销。
ReentrantReadWriteLock
读写锁在同一个时刻允许多个读线程进行访问,但是在写线程访问的时候,所有的读线程和其它写线程均被阻塞。
package com.thread;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class Cache {
static Map<String, Object> map = new HashMap<String, Object>();
static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
static Lock r = rwl.readLock();
static Lock w = rwl.writeLock();
public static final Object get(String key) {
r.lock();
try {
return map.get(key);
} finally {
r.unlock();
}
}
public static final Object put (String key, Objects value) {
w.lock();
try {
return map.put(key, value);
} finally {
w.unlock();
}
}
public static final void clear() {
w.lock();
try {
map.clear();
} finally {
w.unlock();
}
}
}
上面的这段代码就是使用了读写锁来保证map的线程安全。
参考:
1.JAVA并发的艺术
2.http://www.cnblogs.com/dolphin0520/p/3923167.html
JAVA 锁的更多相关文章
- java 锁!
问题:如何实现死锁. 关键: 1 两个线程ta.tb 2 两个对象a.b 3 ta拥有a的锁,同时在这个锁定的过程中,需要b的锁:tb拥有b的锁,同时在这个锁定的过程中,需要a的锁: 关键的实现难点是 ...
- Java锁(一)之内存模型
想要了解Java锁机制.引发的线程安全问题以及数据一致性问题,有必要了解内存模型,机理机制了解清楚了,这些问题也就应声而解了. 一.主内存和工作内存 Java内存模型分为主内存和工作内存,所有的变量都 ...
- Java锁的种类
转载自:---->http://ifeve.com/java_lock_see/ Java锁的种类以及辨析锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchroniz ...
- JAVA锁的可重入性
机制:每个锁都关联一个请求计数器和一个占有他的线程,当请求计数器为0时,这个锁可以被认为是unhled的,当一个线程请求一个unheld的锁时,JVM记录锁的拥有者,并把锁的请求计数加1,如果同一个线 ...
- JAVA 锁之 Synchronied
■ Java 锁 1. 锁的内存语义 锁可以让临界区互斥执行,还可以让释放锁的线程向同一个锁的线程发送消息 锁的释放要遵循 Happens-before 原则(锁规则:解锁必然发生在随后的加锁之前) ...
- java锁与监视器概念 为什么wait、notify、notifyAll定义在Object中 多线程中篇(九)
在Java中,与线程通信相关的几个方法,是定义在Object中的,大家都知道Object是Java中所有类的超类 在Java中,所有的类都是Object,借助于一个统一的形式Object,显然在有些处 ...
- 自己动手写java锁
1.LockSupport的park和unpark方法的基本使用,以及对线程中断的响应性 LockSupport是JDK中比较底层的类,用来创建锁和其他同步工具类的基本线程阻塞原语.java锁和同步器 ...
- Java 锁的学习
个人学习整理,所有资料均来源于网络,非原创. 死锁的四个必要条件:互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用.请求与保持条件(Hold and wait):已经得 ...
- java锁——wait,notify,synchronized
背景:这篇博客用来总结java锁相关的知识点,平时还是要自己多加练习 wait 和 notify以及notifyAll (1).方法介绍1.wait.notify以及notifyAll都是Object ...
随机推荐
- linux shell 命令学习(5) xxd- make a hexdump or do the reverse.
对于标准输入或者给定的文件,显示其16进制的内容.也可以反过来进行转换. xxd -h[elp] xxd [options] [infile [outfile]] xxd -r[evert] [opt ...
- JBOSS集群技术升级版解决方案分享(图示篇)
JBOSS集群技术升级版解决方案分享(实现篇) 前段时间,由于阿堂一直较忙,没有写点什么了,有空时一直在关注"web架构和性能,高并发,Cache层"技术领域的 ...
- java web每天定时执行任务
第一步: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ...
- SQL SERVER 常用字符类型的区别
长度为 n 个字节的固定长度且非 Unicode 的字符数据.n 必须是一个介于 1 和 8,000 之间的数值.存储大小为 n 个字节.char 在 SQL-92 中的同义词为 character. ...
- 加密解密(7)*PKI基础知识(完整)
PKI 基础知识 摘要 本白皮书介绍了加密和公钥基本结构(PKI)的概念和使用 Microsoft Windows 2000 Server 操作系统中的证书服务的基础知识.如果您还不熟悉加密和公钥技术 ...
- [CCPC2016]网赛部分比赛代码
来自HDOJ: 5833 ( Zhu and 772002 ) /* ━━━━━┒ギリギリ♂ eye! ┓┏┓┏┓┃キリキリ♂ mind! ┛┗┛┗┛┃\○/ ┓┏┓┏┓┃ / ┛┗┛┗┛┃ノ) ┓┏ ...
- Git基础(二)
本章内容将介绍第二部分:本地仓储操作.为了加深对每个命令操作的理解,我们可以事先获取一个仓储边学边操作.这里首先 你要明白一个概念,所有本地工作目录下的文件状态无不在乎两种,已跟踪和未跟踪.已跟踪文件 ...
- how bootstrap fit into our website design?
在web相关技术中,HTML代表了content,structure, CSS则负责styling,决定内容是如何展示的,javascript则主要负责interactive, behaviour. ...
- poj 2192 (DP)
这个题题目意思是给你三个字符串str1,str2,str3.将str3从左自右扫描,去匹配str1和str2中的元素,不可重复,若存在一种匹配方法使得str1和str2都被匹配完全了,则输出yes,否 ...
- UVa 699 (二叉树) The Falling Leaves
题意: 按先序方式输入一棵二叉树,节点是带权的,左孩子在父节点的左一个单位,右孩子在父节点的右一个单位,从左到右输出相同水平位置节点之和. 分析: 做了好几道二叉树的题,代码应该也很好理解了.这里ma ...