在前面我们在解决线程同步问题的时候使用了synchronized关键字,今天我们来看看Java 5.0以后提供的线程锁Lock.

Lock接口的实现类提供了比使用synchronized关键字更加灵活和广泛的锁定对象操作,而且是以面向对象的方式进行对象加锁。

		@Override
public void run() {
while(true){
Lock lock = new ReentrantLock();
try {
lock.lock();
Thread.sleep(new Random().nextInt(3000));
String data = readData();
System.out.print("读取数据: " + data);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}
}

读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥,这是由JVM控制的。

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReadWriteLockTest {
static ReadWriteLock rwl = new ReentrantReadWriteLock(); private static String data = null;
public static void main(String[] args) {
Runnable runnable1 = new MyRunnable1();
Runnable runnable2 = new MyRunnable2();
for(int i=0; i<3; i++){
new Thread(runnable1).start();
new Thread(runnable2).start();
}
} static class MyRunnable1 implements Runnable{ @Override
public void run() {
writeData("" + new Random().nextInt(100));
}
} static class MyRunnable2 implements Runnable{ @Override
public void run() {
readData();
}
} private static void writeData(String var){
rwl.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + " 准备写");
Thread.sleep(new Random().nextInt(3000));
data = var;
System.out.println(Thread.currentThread().getName() + " 写完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
rwl.writeLock().unlock();
} } private static void readData(){
rwl.readLock().lock(); //用读锁锁住
try {
System.out.println(Thread.currentThread().getName() + " 准备读");
Thread.sleep(new Random().nextInt(3000));
System.out.println(Thread.currentThread().getName() + " 读完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
rwl.readLock().unlock();
}
}
}

用过Hibernate框架的朋友可能知道,Hibernate查询数据库有缓存机制,如果某个数据在内存中存在则可以并发的去读取,如果缓存中没有数据则需要互斥的去从数据库取数据。

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock; public class CacheDemo {
private Map<String, Object> cache = new HashMap<String, Object>();
public static void main(String[] args) { } private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
/**
* 实现多个并发读,互斥的写
* @param key
* @return
*/
public Object getData(String key){
rwl.readLock().lock();
Object value = null;
try{
value = cache.get(key);
if(value == null){
rwl.readLock().unlock(); //释放读锁
rwl.writeLock().lock(); //添加写锁
try{
if(value == null){ //放置其他线程加载数据
value = "去数据库查询"; //这里模拟从数据库查询
if(value == null){
//TODO 抛出异常
}
}
}finally{
rwl.writeLock().unlock();
}
rwl.readLock().lock(); //锁还给读线程
}
}finally{
rwl.readLock().unlock();
}
return value;
}
}

上面获取数据的大概过程如下:

1、获取读锁,读取数据

2、如果有数据则直接返回,并释放读锁让其他线程读。

3、如果内存中没有数据则从数据库写入内存,释放读锁并添加写锁(这样写入数据就可以达到可以互斥)

4、读入内存后释放写锁并还回读锁(和后面的unlock()对应)

5、如果在添加写锁的时候同时有多个线程,则只能有其中一个线程抢到锁,等拥有锁的线程释放写锁后,其他线程就会抢到写锁,但是此时数据已经写入内存,则需要判断内存数据是否为null如果不为null则直接释放写锁。

Android多线程研究(9)——线程锁Lock的更多相关文章

  1. 孤荷凌寒自学python第三十九天python 的线程锁Lock

    孤荷凌寒自学python第三十九天python的线程锁Lock (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 当多个线程同时操作一个文件等需要同时操作某一对象的情况发生时,很有可能发生冲突, ...

  2. C# 关于线程锁lock的使用方法

    C# 关于线程锁lock的使用方法 原创 2016年09月02日 10:07:05 标签: c# / 线程 / 锁 / lock 11937 在多线程编程中,可能会有许多线程并发的执行一段代码(代码块 ...

  3. Android多线程研究(6)——多线程之间数据隔离

    在上一篇<Android多线程研究(5)--线程之间共享数据>中对线程之间的数据共享进行了学习和研究,这一篇我们来看看怎样解决多个线程之间的数据隔离问题,什么是数据隔离呢?比方说我们如今开 ...

  4. python 多线程中的同步锁 Lock Rlock Semaphore Event Conditio

    摘要:在使用多线程的应用下,如何保证线程安全,以及线程之间的同步,或者访问共享变量等问题是十分棘手的问题,也是使用多线程下面临的问题,如果处理不好,会带来较严重的后果,使用python多线程中提供Lo ...

  5. JAVA多线程提高八:线程锁技术

    前面我们讲到了synchronized:那么这节就来将lock的功效. 一.locks相关类 锁相关的类都在包java.util.concurrent.locks下,有以下类和接口: |---Abst ...

  6. JAVA多线程学习十一-线程锁技术

    前面我们讲到了synchronized:那么这节就来将lock的功效. 一.locks相关类 锁相关的类都在包java.util.concurrent.locks下,有以下类和接口: |---Abst ...

  7. 并发库应用之四 & 线程锁Lock应用

    Java5的线程并发库中,提供了相应的线程锁接口Lock来帮助我们同步处理.Lock比传统线程模型中的synchronized更加面向对象,锁本身也是一个对象,两个线程执行的代码要实现同步互斥效果,就 ...

  8. Android多线程研究(1)——线程基础及源代码剖析

    从今天起我们来看一下Android中的多线程的知识,Android入门easy,可是要完毕一个完好的产品却不easy,让我们从线程開始一步步深入Android内部. 一.线程基础回想 package ...

  9. Android多线程研究(1)——线程基础及源码剖析

    从今天起我们来看一下Android中的多线程的知识,Android入门容易,但是要完成一个完善的产品却不容易,让我们从线程开始一步步深入Android内部. 一.线程基础回顾 package com. ...

随机推荐

  1. 20亿与20亿表关联优化方法(超级大表与超级大表join优化方法)

    记得5年前遇到一个SQL.就是一个简单的两表关联.SQL跑了几乎相同一天一夜,这两个表都非常巨大.每一个表都有几十个G.数据量每一个表有20多亿,表的字段也特别多. 相信大家也知道SQL慢在哪里了,单 ...

  2. Linux 内存管理与系统架构设计

    Linux 提供各种模式(比如,消息队列),但是最著名的是 POSIX 共享内存(shmem,shared memory). Linux provides a variety of schemes ( ...

  3. 关于大数据项目创建时所需setting.xml(博主推荐)

    我目前,收录经常用的是,这两个版本,这个根据博主我本人的经验之谈,最为稳定和合理的. 注意:我的本地路径是在D:/SoftWare/maven/repository,大家自己改为你们自己的即可.   ...

  4. ORA-16047: DGID mismatch between destination setting and standby

    主库有报错如下: ORA-16047: DGID mismatch between destination setting and standby 原因:主库参数设置错误,检查下列参数:log_arc ...

  5. 【2017 Multi-University Training Contest - Team 6】Kirinriki

    [链接]http://acm.hdu.edu.cn/showproblem.php?pid=6103 [题意] 给出一串字符串,从中选出两个不重叠的字符串,使得两个字符串的距离和 <= m 的最 ...

  6. CODEVS——T1979 第K个数

    http://codevs.cn/problem/1979/ 时间限制: 1 s  空间限制: 1000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Descript ...

  7. C++ Traits 技术

    Tarits.特性的复数. c++萃取技术就是指它. 实现方式是模板特化. STL中涉及到iterator的地方常常能用到它. gcc的STL与VS的STL略有区别. vs中下列代码,把鼠标放在ite ...

  8. linux 命令之 apt-get

    apt-get 是一个下载安装软件包的简单命令行接口 使用方法: apt-get [OPTIONS] [COMMANDS] [PACKAGE_NAMES] OPTIONS: -h 帮助信息 -q 输出 ...

  9. 导出查询结果到csv文件

    set colsep ,   set feedback off   set heading off   set trimout on   spool my.csv  select * from emp ...

  10. jQuery的原理

    JQ的原理 jquery-1.xxx :专门为PC端诞生的类库,兼容所有的浏览器 jquery-2.xxx:当初是为了移动端而准备的,所以IE低版本浏览器一般不兼容,但是这个版本针对移动端的事件等操作 ...