锁对象Lock-同步问题更完美的处理方式
Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题,我们拿Java线程(二)中的一个例子简单的实现一下和sychronized一样的效果,代码如下:
- public class LockTest {
- public static void main(String[] args) {
- final Outputter1 output = new Outputter1();
- new Thread() {
- public void run() {
- output.output("zhangsan");
- };
- }.start();
- new Thread() {
- public void run() {
- output.output("lisi");
- };
- }.start();
- }
- }
- class Outputter1 {
- private Lock lock = new ReentrantLock();// 锁对象
- public void output(String name) {
- // TODO 线程输出方法
- lock.lock();// 得到锁
- try {
- for(int i = 0; i < name.length(); i++) {
- System.out.print(name.charAt(i));
- }
- } finally {
- lock.unlock();// 释放锁
- }
- }
- }
这样就实现了和sychronized一样的同步效果,需要注意的是,用sychronized修饰的方法或者语句块在代码执行完之后锁自动释放,而是用Lock需要我们手动释放锁,所以为了保证锁最终被释放(发生异常情况),要把互斥区放在try内,释放锁放在finally内。
如果说这就是Lock,那么它不能成为同步问题更完美的处理方式,下面要介绍的是读写锁(ReadWriteLock),我们会有一种需求,在对数据进行读写的时候,为了保证数据的一致性和完整性,需要读和写是互斥的,写和写是互斥的,但是读和读是不需要互斥的,这样读和读不互斥性能更高些,来看一下不考虑互斥情况的代码原型:
- public class ReadWriteLockTest {
- public static void main(String[] args) {
- final Data data = new Data();
- for (int i = 0; i < 3; i++) {
- new Thread(new Runnable() {
- public void run() {
- for (int j = 0; j < 5; j++) {
- data.set(new Random().nextInt(30));
- }
- }
- }).start();
- }
- for (int i = 0; i < 3; i++) {
- new Thread(new Runnable() {
- public void run() {
- for (int j = 0; j < 5; j++) {
- data.get();
- }
- }
- }).start();
- }
- }
- }
- class Data {
- private int data;// 共享数据
- public void set(int data) {
- System.out.println(Thread.currentThread().getName() + "准备写入数据");
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- this.data = data;
- System.out.println(Thread.currentThread().getName() + "写入" + this.data);
- }
- public void get() {
- System.out.println(Thread.currentThread().getName() + "准备读取数据");
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "读取" + this.data);
- }
- }
部分输出结果:
- Thread-1准备写入数据
- Thread-3准备读取数据
- Thread-2准备写入数据
- Thread-0准备写入数据
- Thread-4准备读取数据
- Thread-5准备读取数据
- Thread-2写入12
- Thread-4读取12
- Thread-5读取5
- Thread-1写入12
我们要实现写入和写入互斥,读取和写入互斥,读取和读取互斥,在set和get方法加入sychronized修饰符:
- public synchronized void set(int data) {...}
- public synchronized void get() {...}
部分输出结果:
- Thread-0准备写入数据
- Thread-0写入9
- Thread-5准备读取数据
- Thread-5读取9
- Thread-5准备读取数据
- Thread-5读取9
- Thread-5准备读取数据
- Thread-5读取9
- Thread-5准备读取数据
- Thread-5读取9
我们发现,虽然写入和写入互斥了,读取和写入也互斥了,但是读取和读取之间也互斥了,不能并发执行,效率较低,用读写锁实现代码如下:
- class Data {
- private int data;// 共享数据
- private ReadWriteLock rwl = new ReentrantReadWriteLock();
- public void set(int data) {
- rwl.writeLock().lock();// 取到写锁
- try {
- System.out.println(Thread.currentThread().getName() + "准备写入数据");
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- this.data = data;
- System.out.println(Thread.currentThread().getName() + "写入" + this.data);
- } finally {
- rwl.writeLock().unlock();// 释放写锁
- }
- }
- public void get() {
- rwl.readLock().lock();// 取到读锁
- try {
- System.out.println(Thread.currentThread().getName() + "准备读取数据");
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "读取" + this.data);
- } finally {
- rwl.readLock().unlock();// 释放读锁
- }
- }
- }
部分输出结果:
- Thread-4准备读取数据
- Thread-3准备读取数据
- Thread-5准备读取数据
- Thread-5读取18
- Thread-4读取18
- Thread-3读取18
- Thread-2准备写入数据
- Thread-2写入6
- Thread-2准备写入数据
- Thread-2写入10
- Thread-1准备写入数据
- Thread-1写入22
- Thread-5准备读取数据
从结果可以看出实现了我们的需求,这只是锁的基本用法,锁的机制还需要继续深入学习。
锁对象Lock-同步问题更完美的处理方式的更多相关文章
- 锁对象-Lock: 同步问题更完美的处理方式 (ReentrantReadWriteLock读写锁的使用/源码分析)
Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题,我 ...
- 锁对象Lock
Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题: public class LockTest { publicstaticv ...
- 同步锁之lock
一. synchronized的缺陷 当一个代码块被synchronized修饰时,同时该代码块被一个线程执行,其他线程便只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况: ...
- Java基础学习笔记: 多线程,线程池,同步锁(Lock,synchronized )(Thread类,ExecutorService ,Future类)(卖火车票案例)
多线程介绍 学习多线程之前,我们先要了解几个关于多线程有关的概念.进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 线 ...
- java锁对象
在Java5中,专门提供了锁对象,利用锁可以方便的实现资源的封锁,用来控制对竞争资源并发访问的控制,这些内容主要集中在java.util.concurrent.locks 包下面,里面有三个重要的接口 ...
- 015-线程同步-synchronized几种加锁方式、Java对象头和Monitor、Mutex Lock、JDK1.6对synchronized锁的优化实现
一.synchronized概述基本使用 为确保共享变量不会出现并发问题,通常会对修改共享变量的代码块用synchronized加锁,确保同一时刻只有一个线程在修改共享变量,从而避免并发问题. syn ...
- Lock同步锁--线程同步
Lock-同步锁 Lock是java5提供的一个强大的线程同步机制--通过显示定义同步锁对象来实现同步.Lock可以显示的加锁.解锁.每次只能有一个线程对lock对象加锁. Lock有ReadLock ...
- Java:多线程,使用同步锁(Lock)时利用Condition类实现线程间通信
如果程序不使用synchronized关键字来保证同步,而是直接使用Lock对象来保证同步,则系统中不存在隐式的同步监视器,也就不能用wait().notify().notifyAll()方法进行线程 ...
- Java:多线程,线程同步,同步锁(Lock)的使用(ReentrantLock、ReentrantReadWriteLock)
关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象.本文探讨Lock对象. synchronize ...
随机推荐
- TCP协议探究(一):报文格式与连接建立终止
一 TCP:传输控制协议报文格式 1 TCP服务 提供面向连接.可靠的字节流服务 面向连接意味着两方通信,不支持多播和广播 可靠性的支持: 应用数据被分割成TCP认为最适合发送的数据块.由TCP传递给 ...
- 谈谈对Spring IOC的理解(转发)
学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...
- luogu4777[模板]拓展中国剩余定理题解
题目链接 https://www.luogu.org/problemnew/show/P4777 分析 扩展\(CRT\)就是解决模数不互质的情况,说是扩展\(CRT\),其实都是扩欧... 先来考虑 ...
- get_object_or_404返回404(400)
get_object_or_404:第一个参数为queryset,第二个参数必须以关键字的形式传递,否则报错
- 【php设计模式】组合模式
定义: 是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结构型模式,它创建了对象组的树形结构. 应用场景: 部分.整体场景,如 ...
- vue-添加全局扩展方法
1.添加全局方法或者属性,如: vue-custom-element 2.添加全局资源:指令/过滤器/过渡等,如 vue-touch 3.通过全局 mixin 方法添加一些组件选项,如: vue-ro ...
- 微信小程序跳到指定页面不生效
wx.redirectTo({ url: './index', }) wx.navigateTo({ url: './index', }) 用了这两种都没生效,点击没跳转,也没报错 后来想了下是不是因 ...
- ARM与x86 CPU架构对比
CISC(复杂指令集计算机)和RISC(精简指令集计算机)是当前CPU的两种架构.它们的区别在于不同的CPU设计理念和方法.早期的CPU全部是CISC架构,它的设计目的是CISC要用最少的机器语言指令 ...
- c# MVC方式文件上传
MVC控制器中代码 index.cshtml <form action="/Home/Upload" method="post" enctype=&quo ...
- hivesql中的concat函数,concat_ws函数,concat_group函数之间的区别
一.CONCAT()函数CONCAT()函数用于将多个字符串连接成一个字符串.使用数据表Info作为示例,其中SELECT id,name FROM info LIMIT 1;的返回结果为 +---- ...