首页 技术 正文
技术 2022年11月15日
0 收藏 895 点赞 4,769 浏览 2627 个字

理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的.

1.如何创建锁?

Lock lock = new ReentrantLock();

2.如何使用锁?

可以参看Lock文档,其使用格式如下:

class X {
private final ReentrantLock lock = new ReentrantLock();
// ... public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}

在要用的方法前加上锁,比如写操作,然后在finally中将锁打开.

这里,将前文java核心知识点学习—-多线程并发之线程同步中的代码改用Lock实现数据同步,改写代码如下:

package com.amos.concurrent;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/**
* @ClassName: LockTest
* @Description: Lock学习
* @author: amosli
* @email:hi_amos@outlook.com
* @date Apr 22, 2014 1:48:36 AM
*/
public class LockTest {
public static void main(String[] args) {
new LockTest().init();
} private void init() {
final OutPuter outPuter = new OutPuter();
// 新建一个线程
new Thread(new Runnable() {
public void run() {
while (true) {
// 休息10ms
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outPuter.output("hi_amos");// 输出
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outPuter.output("amosli");
}
}
}).start();
} static class OutPuter {
// 方式1:使用synchronized关键字
// public synchronized void output(String name) {
// int length = name.length();
// for (int i = 0; i < length; i++) {
// System.out.print(name.charAt(i));
// }
// System.out.println();
// } // 方式2:使用Lock锁
Lock lock = new ReentrantLock(); public void output(String name) {
lock.lock();// 加锁
int length = name.length();
// 输出name,逐个字节读取,并输出
try {
for (int i = 0; i < length; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
} finally {
lock.unlock();// 解锁
}
}
}
}

3.synchronized关键字与Lock的区别?

1).Lock是Java5中的新特性,更加面向对象.更类似于生活中的锁.

2).Lock锁一般需要手动开启和关闭,而synchronized则不需要.

建议优先使用Lock.

4.注意事项:

1)多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥.

2)要实现两个线程互斥,那么要将锁加到同一个被访问对象上.

3)如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁,总之,读的时候用读锁,写的时候用写锁!

5.设计一个缓存系统

什么是缓存系统? 就是看本地是否已经缓存过此数据,如果已经缓存过,那就直接拿来用;如果没有缓存过,那就查询数据库.

下面看代码:

private Map<String, Object> cache = new HashMap<String, Object>();    public synchronized Object getData(String key){
Object object = cache.get(key);
if (object==null) {
object = "1323";//实际是去queryDB();
}
return object;
}

这里其实是一个超级简单的缓存系统,原理就是:第一次访问的时候把值存入到cache中,第二次访问时,先去看cache中是否有值如果有值,那么就直接去取值,而不是从数据库中去取.

为什么要加上synchronized? 这是为了保持数据互斥,访问的时候不相互影响,因为其中有对object进行赋值操作,这是一个写操作,所以最好加上锁.

如何优化?

private ReadWriteLock rwl = new ReentrantReadWriteLock();
public synchronized Object getData(String key){
rwl.readLock();//read lock
Object object = cache.get(key);
try{
if (object==null) {
rwl.readLock().unlock();//释放锁
rwl.writeLock().lock();//对写加锁
try{
object = "1323";//实际是去queryDB();
}finally{
rwl.writeLock().unlock();
}
}
}finally{
rwl.readLock().unlock();
}
return object;
}

上面的代码运用到了刚学到的知识,对所有读和写进行加锁,以保持线程间的互斥,要特别注意的是要在finally中把锁打开,不管程序是否执行成功,因为如果不解锁,那么程序将会产生死锁,关于死锁,将在接下来的文章中介绍.

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,078
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,553
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,402
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,177
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,814
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,898