首页 > 编程语言 >Java编程思想21

Java编程思想21

时间:2022-12-26 19:22:27浏览次数:36  
标签:Java 21 显式 lock 编程 finally Lock public captured

2. 使用显示的Lock对象
  Java SE5的java.util.concurrent类库还包含有定义在java.util.concurrent.locks中的显式的互斥机制。Lock对象必须被显式地创建、锁定和释放。因此,它与内建的锁形式相比,代码缺乏优雅性。但是,对于解决某些类型的问题来说,它更加灵活。下面用显式的Lock重写的是SyncEventGenerator.java:

package concurrency;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* @author Mr.Sun
* @date 2022年09月04日 11:13
*
* 使用显示的Lock对象重写SyncEventGenerator
*/
public class MutexEventGenerator extends IntGenerator{
private int currentCountVal = 0;
private Lock lock = new ReentrantLock();

@Override
public int next() {
lock.lock();
try {
++currentCountVal;
Thread.yield();
++currentCountVal;
return currentCountVal;
} finally {
lock.unlock();
}
}

public static void main(String[] args) {
EventChecker.test(new MutexEventGenerator());
}
}

 

MutexEvenGenerator添加了一个被互斥调用的锁,并使用lock()和unlock()方法在next()内部创建了临界资源。当你在使用Lock对象时,将这里所示的惯用法内部化是很重要的:紧接着的对lock()的调用,你必须放置在finally子句中带有unlock()的try-finally语句中。注意,return 语句必须在try子句中出现,以确保unlock()不会过早发生,从而将数据暴露给了第二个任务。
  尽管try-finally所需的代码比synchronized关键字要多,但是这也代表了显式的Lock对象的优点之一。如果在使用synchronized关键字时,某些事物失败了,那么就会抛出一个异常。但是你没有机会去做任何清理工作,以维护系统使其处于良好状态。有了显式的Lock对象,你就可以使用finally子句将系统维护在正确的状态了。
  大体上,当你使用synchronized关键字时,需要写的代码量更少,并且用户错误出现的可能性也会降低,因此通常只有在解决特殊问题时,才使用显式的Lock对象。例如,用synchronized 关键字不能尝试着获取锁且最终获取锁会失败,或者尝试着获取锁一段时间,然后放弃它,要实现这些,你必须使用concurrent类库∶

package concurrency;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
* @author Mr.Sun
* @date 2022年09月04日 11:20
*
* 演示使用Lock对象尝试获取锁
*/
public class AttemptLocking {
private ReentrantLock lock = new ReentrantLock();
public void unTimed () {
boolean captured = lock.tryLock();
try {
System.out.println("tryLock(): " + captured);
} finally {
// 获取到锁才能执行释放锁操作,否则会出现IllegalMonitorStateException异常
if (captured) {
lock.unlock();
}
}
}

public void timed () {
boolean captured = false;
try {
captured = lock.tryLock(2, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}

try {
System.out.println("lock.tryLock(2, TimeUnit.MINUTES): " + captured);
} finally {
if (captured) {
lock.unlock();
}
}
}

public static void main(String[] args) throws InterruptedException {
final AttemptLocking al = new AttemptLocking();
al.unTimed(); // True -- 锁是可用的
al.timed(); // True -- 锁是可用的

// 现在创建一个单独的任务来获取锁
new Thread() {
{setDaemon(true);}

@Override
public void run() {
al.lock.lock();
System.out.println("acquired");
}
}.start();
// 给第二个任务一个机会
Thread.sleep(100);
al.unTimed(); // false -- lock grabbed by task
al.timed(); // false -- lock grabbed by task
}

} /* Output:
tryLock(): true
lock.tryLock(2, TimeUnit.MINUTES): true
acquired
tryLock(): false
lock.tryLock(2, TimeUnit.MINUTES): false
*///:~

 

ReentrantLock允许你尝试着获取但最终未获取锁,这样如果其他人已经获取了这个锁,那你就可以决定离开去执行其他一些事情,而不是等待直至这个锁被释放,就像在untimed()方法中所看到的。在timed()中,做出了尝试去获取锁,该尝试可以在2秒之后失败(注意,使用了Java SE5的TimeUnit类来指定时间单位)。在main()中,作为匿名类而创建了一个单独的Thread,它将获取锁,这使得untimed()和timed()方法对某些事物将产生竞争。
  显式的Lock对象在加锁和释放锁方面,相对于内建的synchronized锁来说,还赋予了你更细粒度的控制力。这对于实现专有同步结构是很有用的,例如用于遍历链接列表中的节点的节节传递的加锁机制(也称为锁耦合),这种遍历代码必须在释放当前节点的锁之前捕获下一个节点的锁。

标签:Java,21,显式,lock,编程,finally,Lock,public,captured
From: https://www.cnblogs.com/LvJinshuai/p/17006592.html

相关文章

  • 实验5 结构体应用编程
    实验三#include<stdio.h>#include<string.h>#defineN100typedefstruct{charnum[10];//学号ints1;//期末成绩ints2......
  • 火山中文编程 -- 存款本息和
    例子:假设有本金1000元,想存一年,有三种方法可选择:活期,年利率为0.0036;一年期定期,年利率为0.0225;存两次半年定期,年利率为0.0198。请分别计算出一年后按3种方法所得到的本息和。......
  • 火山中文编程 -- 温度转换
    例子:有人用温度计测量出用华氏温度98°F,现在要求用火山中文编程实现,把它转换为以摄氏法表示的温度。分析:摄氏度=(5/9)*(华氏度-32)一、新建MFC窗口,设置好布局二、编写代码三、运......
  • Java 批量大文件上传下载
    ​ 文件上传是一个老生常谈的话题了,在文件相对比较小的情况下,可以直接把文件转化为字节流上传到服务器,但在文件比较大的情况下,用普通的方式进行上传,这可不是一个好的办法......
  • fastjson提取json返回值(java)
    返回json数据:{"data":{"offset":2,"total":2952,"restTotal":2950,"dataList":[{"ISBN":"9787539197456",......
  • JavaScript 中0.1+0.2 不等于 0.3 的问题
    在JavaScript中,有时候你可能会发现0.1+0.2不等于0.3。这是因为JavaScript使用的是浮点数来表示小数,而浮点数在计算机内部是用二进制表示的,这导致了一些精度问题。......
  • 如何在Java里进行数学公式计算?
    我们在平常开发的时候,难免会遇到涉及数学公式计算的业务场景。例如给一个公式,(1+P)*T=?,其中P和T是两个变量,当T=11、P=110时,这个公式计算的结果是多少呢?下面给出具体实现的......
  • oss连接出现java.lang.IllegalArgumentException: Oss endpoint can't be empty.问题
    场景:在bootstrap.properties中编写nacos的配置,读取在nacos中定义的数据集连接ossspringboot版本为2.6.8结果就出现了以上错误原因:通过查找资料后发现,在springboot2.4......
  • Java同步器之ReentrantLock源码分析(一)
    一、概述ReentrantLock是Java并发包中提供的一个可重入的互斥锁。ReentrantLock和synchronized在基本用法,行为语义上都是类似的,同样都具有可重入性。只不过相比原生的Syn......
  • JAVA基于权重的抽奖
     如有4个元素A、B、C、D,权重分别为1、2、3、4,随机结果中A:B:C:D的比例要为1:2:3:4。总体思路:累加每个元素的权重A(1)-B(3)-C(6)-D(10),则4个元素的的权重管辖区间分别为[0,1......