当前位置: 首页 > news >正文

富阳网站企业营销案例

富阳网站,企业营销案例,wordpress 禁用admin,s2b2c商业模式目录 1 互斥性 2 公平性 3 可重入性 4 获取和释放锁 5 尝试获取锁 6 可中断的锁定 7 条件变量 8 性能 9 使用场景 ReentrantLock 是 Java 提供的一种可重入的互斥锁,位于 java.util.concurrent.locks 包中,它实现了 Lock 接口。这个锁提供了与内…

目录

1 互斥性

2 公平性

3 可重入性

4 获取和释放锁

5 尝试获取锁

6 可中断的锁定

7 条件变量

8 性能

9 使用场景


ReentrantLock 是 Java 提供的一种可重入的互斥锁,位于 java.util.concurrent.locks 包中,它实现了 Lock 接口。这个锁提供了与内置监视器锁(通过 synchronized 关键字实现)类似的互斥性和内存可见性,但具有更强大的功能和灵活性。以下是 ReentrantLock 的一些基本概念:

1 互斥性

ReentrantLock 可以确保同一时间只有一个线程可以执行由该锁保护的代码块,从而避免了竞态条件。

2 公平性

  • 非公平锁:默认情况下,ReentrantLock 是非公平的。这意味着线程获取锁的顺序并不是按照它们请求锁的顺序来确定的。非公平锁通常提供更高的吞吐量。
  • 公平锁:当创建 ReentrantLock 实例时,可以通过传入 true 参数来指定为公平锁。公平锁保证线程将按照它们请求锁的顺序获得锁。这可能会降低吞吐量,但能减少饥饿现象。

示例代码:默认是非公平锁,如果需要公平锁,则在构造函数中传入 true

import java.util.concurrent.locks.ReentrantLock;// 默认非公平锁
ReentrantLock lock = new ReentrantLock();// 公平锁
ReentrantLock fairLock = new ReentrantLock(true);

3 可重入性

可重入意味着如果一个线程已经持有某个锁,那么它可以再次获取这个锁而不会被阻塞。这是非常有用的特性,因为它允许方法在调用其他可能也需要相同锁的方法时不会导致死锁。

示例代码:

public void reentrantExample() {lock.lock();try {// 第一次获取锁System.out.println("First time locked, thread: " + Thread.currentThread().getName());// 在已经持有锁的情况下再次获取锁lock.lock();try {System.out.println("Second time locked, thread: " + Thread.currentThread().getName());} finally {lock.unlock();  // 释放第二次获取的锁}} finally {lock.unlock();  // 释放第一次获取的锁}
}

输出结果:

First time locked, thread: main
Second time locked, thread: main

使用可重入锁的具体例子:假设有一个类,其中包含一个递归方法,且这个方法需要是线程安全的。由于方法会多次调用自身,因此需要一个可重入锁来确保同一个线程可以重复获取锁。

import java.util.concurrent.locks.ReentrantLock;public class FactorialCalculator {private final ReentrantLock lock = new ReentrantLock();public int factorial(int number) {lock.lock(); // 获取锁try {if (number <= 1) {return 1;} else {return number * factorial(number - 1); // 递归调用}} finally {lock.unlock(); // 释放锁}}
}

4 获取和释放锁

获取锁通过调用 lock() 方法,释放锁则通过 unlock() 方法。通常建议在 finally 块中释放锁,以确保即使发生异常也能正确释放锁。

public void doSomething() {lock.lock();try {// 执行同步代码} finally {lock.unlock();}
}

5 尝试获取锁

tryLock() 方法尝试获取锁,如果无法立即获得锁,则返回 false,不会阻塞线程。

if (lock.tryLock()) {  // 尝试获取锁,如果无法获取,则立即返回falsetry {// 执行同步代码} finally {lock.unlock();}
} else {// 锁未获得时的操作
}

tryLock() 方法有两个版本:

  • 无参数的 tryLock():尝试获取锁,如果锁可用则立即获取并返回 true,否则立即返回 false
  • 带超时的 tryLock(long timeout, TimeUnit unit):尝试获取锁,如果在指定的时间内可以获取到锁,则返回 true;如果超过了指定时间仍无法获取到锁,则返回 false

具体使用示例:

无参数的 tryLock():

import java.util.concurrent.locks.ReentrantLock;public class TryLockExample {private final ReentrantLock lock = new ReentrantLock();public void doWork() {if (lock.tryLock()) {  // 尝试获取锁try {// 执行需要同步的操作System.out.println("Thread " + Thread.currentThread().getName() + " is doing work.");} finally {lock.unlock();  // 确保释放锁}} else {// 如果无法获取锁,执行其他操作System.out.println("Thread " + Thread.currentThread().getName() + " could not get the lock and will do something else.");}}public static void main(String[] args) {TryLockExample example = new TryLockExample();// 创建两个线程来调用 doWork 方法Thread t1 = new Thread(() -> example.doWork(), "Thread-1");Thread t2 = new Thread(() -> example.doWork(), "Thread-2");t1.start();t2.start();}
}

在这个例子中,如果 Thread-1 先获取到了锁,那么 Thread-2 将无法获取锁,并且会直接输出“无法获取锁”的信息。

带超时的 tryLock(long timeout, TimeUnit unit) :

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;public class TryLockWithTimeoutExample {private final ReentrantLock lock = new ReentrantLock();public void doWork() {boolean locked = false;try {// 尝试在5秒内获取锁locked = lock.tryLock(5, TimeUnit.SECONDS);if (locked) {// 执行需要同步的操作System.out.println("Thread " + Thread.currentThread().getName() + " is doing work.");} else {// 如果在5秒内无法获取锁,执行其他操作System.out.println("Thread " + Thread.currentThread().getName() + " could not get the lock within 5 seconds and will do something else.");}} catch (InterruptedException e) {// 处理中断异常Thread.currentThread().interrupt();System.out.println("Thread " + Thread.currentThread().getName() + " was interrupted while waiting for the lock.");} finally {if (locked) {lock.unlock();  // 确保释放锁}}}public static void main(String[] args) {TryLockWithTimeoutExample example = new TryLockWithTimeoutExample();// 创建两个线程来调用 doWork 方法Thread t1 = new Thread(() -> example.doWork(), "Thread-1");Thread t2 = new Thread(() -> example.doWork(), "Thread-2");t1.start();t2.start();}
}

在这个例子中,如果 Thread-1 持有锁超过5秒钟,那么 Thread-2 将会在等待5秒后放弃尝试获取锁,并执行相应的逻辑。

使用场景

  • 避免死锁:当多个线程试图以不同的顺序获取多个锁时,可能会导致死锁。使用 tryLock() 可以帮助检测这种情况,并采取适当的措施。
  • 提高响应性:在某些情况下,你可能不希望线程一直等待锁,而是希望线程能够快速响应其他任务。这时可以使用 tryLock() 来检查锁是否可用,如果不可用就立即执行其他工作。
  • 资源竞争控制:在资源有限的情况下,可以使用 tryLock() 来尝试获取资源,如果获取不到则可以选择放弃或重试。

6 可中断的锁定

lockInterruptibly() 方法允许在等待获取锁的过程中响应中断。

try {lock.lockInterruptibly();  // 尝试获取锁,可以响应中断try {// 执行同步代码} finally {lock.unlock();}
} catch (InterruptedException e) {// 处理中断情况
}

示例代码:

import java.util.concurrent.locks.ReentrantLock;public class CancellableTask {private final ReentrantLock lock = new ReentrantLock();private boolean isCancelled = false;public void runTask() {Thread thread = new Thread(() -> {try {// 尝试获取锁,同时可以响应中断lock.lockInterruptibly();try {// 模拟任务执行while (!isCancelled) {System.out.println("Task is running...");// 假设任务需要一段时间完成Thread.sleep(1000);}} finally {lock.unlock();}} catch (InterruptedException e) {System.out.println("Task was interrupted, stopping execution.");// 通常在这里你会清理资源并退出// 重新设置中断状态,以便调用者知道该线程已被中断Thread.currentThread().interrupt();}});thread.start();// 在某个时刻决定取消任务try {Thread.sleep(3000); // 等待几秒钟} catch (InterruptedException e) {e.printStackTrace();}isCancelled = true;thread.interrupt(); // 中断线程}public static void main(String[] args) {CancellableTask task = new CancellableTask();task.runTask();}
}

当主线程决定取消任务时,它会中断工作线程。工作线程会在 lockInterruptibly() 调用处立即响应中断,并抛出 InterruptedException,从而允许任务快速终止。 

输出结果:

Task is running...
Task is running...
Task is running...
Task was interrupted, stopping execution.

除了使用 lockInterruptibly() 来实现中断锁,还可以使用带超时的 tryLock(long timeout, TimeUnit unit)来达成这一目的。以下是例子:

import java.util.concurrent.locks.ReentrantLock;public class ResourceService {private final ReentrantLock resourceLock = new ReentrantLock();public void useResource() {Thread thread = new Thread(() -> {try {if (resourceLock.tryLock()) {try {// 使用资源System.out.println("Using resource...");Thread.sleep(10000); // 模拟长时间操作} finally {resourceLock.unlock();}} else {System.out.println("Could not acquire the resource, operation is cancelled.");}} catch (InterruptedException e) {System.out.println("Resource usage was interrupted, releasing the resource.");resourceLock.unlock(); // 如果已经获得锁,则释放Thread.currentThread().interrupt(); // 保持中断状态}});thread.start();// 在某个时刻决定取消使用资源的操作try {Thread.sleep(5000); // 等待几秒钟} catch (InterruptedException e) {e.printStackTrace();}thread.interrupt(); // 中断线程}public static void main(String[] args) {ResourceService service = new ResourceService();service.useResource();}
}

是的,tryLock(long time, TimeUnit unit) 方法也可以响应中断。当一个线程调用 tryLock(long time, TimeUnit unit) 时,它会尝试在指定的时间内获取锁。如果在这段时间内没有获取到锁,方法将返回 false。此外,如果在此期间线程被中断,该方法会立即抛出 InterruptedException 并且不会获取锁。 

注意:ReentrantLocklock() 方法确实不会响应中断。当一个线程调用 lock() 试图获取锁时,如果锁已经被其他线程持有,那么该线程将一直阻塞,直到它能够获取到锁为止。即使在此期间该线程被中断(例如通过调用 Thread.interrupt()),它也不会抛出 InterruptedException 或者以其他方式退出等待状态。只有在获取到锁之后,中断状态才会被检查。

7 条件变量

ReentrantLock 提供了条件变量 Condition,它可以替代传统的 Object.wait/notify 机制。这些对象类似于 Object 类中的 wait/notify 机制,但是更加灵活。每个 Condition 实例都可以独立地挂起和唤醒线程,这对于复杂的同步需求是非常有用的。

下面是一个具体的例子,展示了如何使用条件变量来实现生产者-消费者模式

在这个模式中,有一个共享缓冲区,生产者向缓冲区添加元素,消费者从缓冲区移除元素。当缓冲区满时,生产者必须等待;当缓冲区空时,消费者必须等待。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.LinkedList;public class ProducerConsumerExample {private final int BUFFER_SIZE = 5; // 缓冲区大小private final LinkedList<Integer> buffer = new LinkedList<>();private final ReentrantLock lock = new ReentrantLock();private final Condition notFull = lock.newCondition(); // 缓冲区不满的条件private final Condition notEmpty = lock.newCondition(); // 缓冲区不空的条件public void put(int value) throws InterruptedException {lock.lock();try {// 如果缓冲区已满,则等待while (buffer.size() == BUFFER_SIZE) {notFull.await();}// 向缓冲区添加元素buffer.add(value);System.out.println("Produced: " + value);// 唤醒可能正在等待的消费者notEmpty.signal();} finally {lock.unlock();}}public int get() throws InterruptedException {lock.lock();try {// 如果缓冲区为空,则等待while (buffer.isEmpty()) {notEmpty.await();}// 从缓冲区移除元素int value = buffer.removeFirst();System.out.println("Consumed: " + value);// 唤醒可能正在等待的生产者notFull.signal();return value;} finally {lock.unlock();}}public static void main(String[] args) {final ProducerConsumerExample example = new ProducerConsumerExample();Thread producerThread = new Thread(() -> {for (int i = 0; i < 20; i++) {try {example.put(i);Thread.sleep(100); // 模拟生产时间} catch (InterruptedException e) {Thread.currentThread().interrupt();break;}}});Thread consumerThread = new Thread(() -> {for (int i = 0; i < 20; i++) {try {example.get();Thread.sleep(200); // 模拟消费时间} catch (InterruptedException e) {Thread.currentThread().interrupt();break;}}});producerThread.start();consumerThread.start();try {producerThread.join();consumerThread.join();} catch (InterruptedException e) {e.printStackTrace();}}
}

代码解释: 

  • ReentrantLock 和 Condition:我们使用 ReentrantLock 来保护对共享资源(即缓冲区)的访问,并且创建了两个条件变量 notFull 和 notEmpty
  • put() 方法:生产者调用此方法向缓冲区添加数据。如果缓冲区已满,则生产者将调用 notFull.await() 等待直到有空间可用。一旦添加了数据,就通过 notEmpty.signal() 通知等待中的消费者。
  • get() 方法:消费者调用此方法从缓冲区获取数据。如果缓冲区为空,则消费者将调用 notEmpty.await() 等待直到有数据可用。一旦取出了数据,就通过 notFull.signal() 通知等待中的生产者。
  • 主线程:启动生产者和消费者线程,并等待它们完成。

8 性能

ReentrantLock 在某些情况下比 synchronized 更高效,尤其是在高度竞争的情况下。这是因为 ReentrantLock 可以使用自旋而不是完全阻塞来等待锁,这样可以减少上下文切换的成本。

9 使用场景

  • 当你需要比 synchronized 更细粒度的控制时,例如尝试获取锁、响应中断或使用多个条件变量。
  • 当你需要实现公平锁时。
  • 当你希望在性能上有所提升,并且能够处理高级并发模式时。

示例代码:

import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockExample {private final ReentrantLock lock = new ReentrantLock();public void doSomething() {// 获取锁lock.lock();try {// 执行需要同步的操作System.out.println("Thread " + Thread.currentThread().getName() + " is doing something.");} finally {// 确保锁最终会被释放lock.unlock();}}public static void main(String[] args) {ReentrantLockExample example = new ReentrantLockExample();// 创建两个线程来调用 doSomething 方法Thread t1 = new Thread(() -> example.doSomething(), "Thread-1");Thread t2 = new Thread(() -> example.doSomething(), "Thread-2");t1.start();t2.start();}
}

在这个例子中,doSomething 方法使用 ReentrantLock 来确保每次只有一个线程可以执行其中的代码。注意在 finally 块中释放锁,以防止因异常导致锁未被释放的情ss

http://www.tj-hxxt.cn/news/15514.html

相关文章:

  • 苏州建网站的公如何关闭2345网址导航
  • 网站开发充值功能semiconductor
  • 国外的外贸b2b网站有哪些百度百家号注册
  • 网站制作 流程百度seo价格查询系统
  • 本地网站构建常州网站优化
  • 简洁大方 网站app营销策划方案
  • 绍兴网站建设方案优化大师app下载安装
  • 老网站做seo能不能重新注册刚刚发生了一件大事
  • 嘉兴做网站的公司有哪些肇庆百度快照优化
  • 遂宁建设局网站首页新手怎么做销售
  • 如何设计优秀的公司网站加强服务保障满足群众急需i
  • wordpress仿站教程百度云中国广告网
  • 二手网站专业做附近人的有吗国内广告联盟平台
  • 湖北做网站价格创建网站要钱吗
  • 山东省住房和城乡建设厅焊工证seo编辑是干什么的
  • 一键免费搭建手机网站网络营销专业如何
  • 莆田网站建设模板什么平台可以发广告引流
  • 东莞专业的网站建设网络推广宁波最好的推广平台
  • 盘古网做网站多少钱百度app怎么找人工客服
  • 怎样在手机上网站建设推广引流吸引人的标题
  • wordpress jetpack中国湘潭关键词优化服务
  • 北京土巴兔全包装修价格表优化落实新十条措施
  • ps切图做网站app推广软文范文
  • 威海哪里可以做网站上海营销公司
  • 修改wordpress的站点地址大型网站建设
  • 网站开发属于什么会计科目百度seo优化哪家好
  • 深圳做网站网络公司怎么优化一个网站
  • 婚恋交友网站建设策划今天最新新闻摘抄
  • 做视频素材网站百度极速版app下载安装
  • 深圳手机网站建设公司济南疫情最新消息