网站建设技术合作合同书,做网站有维护费是什么费用,做网站应该用什么镜像,内部网站做登陆内部链接Java11中的Lock接口提供lock()和lockInterruptibly()两种锁定方法#xff0c;用于获取锁#xff0c;但处理线程中断时有所不同#xff0c;lock()使线程等待直到锁释放#xff0c;期间无视中断#xff1b;而lockInterruptibly()在等待中若收到中断请求#xff0c;会立即响… Java11中的Lock接口提供lock()和lockInterruptibly()两种锁定方法用于获取锁但处理线程中断时有所不同lock()使线程等待直到锁释放期间无视中断而lockInterruptibly()在等待中若收到中断请求会立即响应并抛出异常这种机制使lockInterruptibly()更灵活能更好处理线程中断避免无意义等待提升系统响应性和效率。 定义 在Java 11中Lock接口提供了两种锁定方法lock()和lockInterruptibly()这两种方法虽然都是为了获取锁但在处理线程中断时有着显著的不同。
lock()方法是一种基本的锁定机制当一个线程调用这个方法时如果锁已经被其他线程持有那么调用线程就会进入等待状态直到锁被释放在等待的过程中这个线程会无视中断请求也就是说即使有其他线程调用了这个等待线程的interrupt()方法它也不会有任何响应依旧会“执着”地等待锁的释放。
而lockInterruptibly()方法则不同它提供了一种更加“灵活”的锁定机制当一个线程调用这个方法时如果锁已经被其他线程持有那么这个线程同样会进入等待状态但是在等待的过程中如果这个线程收到了中断请求即有其他线程调用了它的interrupt()方法那么它就会立即响应中断不再等待锁的释放而是抛出一个InterruptedException异常。
举个例子来说明这两种方法的区别假设有一个仓库只有一把钥匙可以打开这里把钥匙比作锁现在有两个人线程都想进入仓库取东西
如果第一个人使用lock()方法那么在他拿到钥匙并进入仓库之前即使有人叫他发送中断请求他也不会理睬直到他取完东西出来并把钥匙交给下一个人。如果第一个人使用lockInterruptibly()方法那么在他等待钥匙的时候如果有人叫他发送中断请求他就会立即响应放弃等待转而去做其他事情。
lockInterruptibly()方法就提供了一种更加“人性化”的锁定机制能够更好地处理线程的中断请求避免线程长时间无意义地等待锁的释放。
代码案例 使用lock()
Lock接口通过其实现类ReentrantLock来使用以下是一个使用ReentrantLock和lock()方法的示例代码该代码模拟了上面描述的“仓库”案例在这个例子中有一个Warehouse类它包含一个资源并且使用ReentrantLock来控制对这个资源的访问如下代码
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; // 仓库类使用Lock来控制访问
public class Warehouse { private final Lock lock new ReentrantLock(); private String resource Goods inside the warehouse; // 仓库中的资源 // 获取仓库资源的方法 public void accessResource() { lock.lock(); // 获取锁 try { // 模拟长时间的操作 try { Thread.sleep(1000); } catch (InterruptedException e) { // 注意这里不会响应中断因为使用了lock()方法 e.printStackTrace(); } System.out.println(Thread.currentThread().getName() accessed the resource: resource); } finally { lock.unlock(); // 释放锁 } }
} // 客户端代码模拟两个线程同时尝试访问仓库资源
public class Client { public static void main(String[] args) { Warehouse warehouse new Warehouse(); // 创建并启动两个线程它们将尝试访问仓库资源 Thread thread1 new Thread(() - warehouse.accessResource(), Thread-1); Thread thread2 new Thread(() - warehouse.accessResource(), Thread-2); thread1.start(); thread2.start(); // 注意由于使用了lock()方法即使尝试中断线程它们也不会响应直到它们自然地完成操作 }
}在上面代码中Warehouse类有一个accessResource方法它使用lock()方法获取锁并在finally块中释放锁以确保锁总是会被释放无论是否发生异常Client类创建了两个线程它们几乎同时尝试访问Warehouse的资源由于lock()方法不会响应中断因此即使一个线程在持有锁时被中断它也会继续执行直到释放锁。
这个代码输出内容如下因为ReentrantLock确保了资源在任何时候只被一个线程访问如下
Thread-1 accessed the resource: Goods inside the warehouse
Thread-2 accessed the resource: Goods inside the warehouse使用lockInterruptibly()
下面使用Lock接口中的lockInterruptibly()方法的Java代码示例演示如何中断一个正在等待获取锁的线程如下代码
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; // 仓库类使用Lock来控制访问
public class Warehouse { private final Lock lock new ReentrantLock(); private String resource Goods inside the warehouse; // 仓库中的资源 // 可响应中断地获取仓库资源的方法 public void accessResourceInterruptibly() throws InterruptedException { lock.lockInterruptibly(); // 可响应中断地获取锁 try { // 模拟长时间的操作 Thread.sleep(2000); System.out.println(Thread.currentThread().getName() accessed the resource: resource); } finally { lock.unlock(); // 无论如何都会释放锁 } }
} // 客户端代码模拟两个线程同时尝试访问仓库资源并中断其中一个线程
public class Client { public static void main(String[] args) throws InterruptedException { Warehouse warehouse new Warehouse(); // 创建第一个线程并启动它将尝试访问仓库资源 Thread thread1 new Thread(() - { try { warehouse.accessResourceInterruptibly(); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() was interrupted while waiting for the lock.); } }, Thread-1); thread1.start(); // 让第一个线程有时间去获取锁 Thread.sleep(500); // 创建第二个线程它也将尝试访问仓库资源但会中断它 Thread thread2 new Thread(() - { try { warehouse.accessResourceInterruptibly(); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() was interrupted while waiting for the lock.); } }, Thread-2); thread2.start(); // 中断第二个线程因为它可能正在等待获取锁 Thread.sleep(500); thread2.interrupt(); // 等待第一个线程完成 thread1.join(); }
}在上面代码中Warehouse类有一个accessResourceInterruptibly方法它使用lockInterruptibly()方法来获取锁如果线程在等待获取锁的过程中被中断它将抛出InterruptedException异常。
在Client类的main方法中创建了两个线程第一个线程thread1启动后让它先运行一段时间以确保它能够获取到锁然后启动第二个线程thread2并立即中断它由于thread2在调用lockInterruptibly()时可能会被中断因此它应该捕获InterruptedException并打印出一条消息表明它在等待锁的过程中被中断了。
输出如下
Thread-1 accessed the resource: Goods inside the warehouse
Thread-2 was interrupted while waiting for the lock.这个输出表明thread1成功访问了资源而thread2则在等待获取锁的过程中被中断了。
核心总结 1、使用lock方法的情况
当需要确保一段代码或一系列操作以原子方式执行即在这段代码执行期间不会被其他线程干扰时可以使用lock方法lock方法会尝试获取锁如果锁当前被其他线程持有那么当前线程将被挂起即阻塞直到锁变得可用这是一种基本的线程同步机制用于防止多个线程同时访问共享资源从而避免数据不一致和其他并发问题。
2、使用lockInterruptibly方法的情况
与lock方法类似lockInterruptibly方法也用于获取锁以保护临界区但是lockInterruptibly有一个额外的特性它是可响应中断的这意味着如果当前线程在等待获取锁的过程中被中断例如通过调用Thread.interrupt方法lockInterruptibly将不会无限期地等待下去而是会立即抛出InterruptedException异常这使得线程能够更灵活地处理中断例如可以在被中断时执行一些清理操作或通知其他线程。
3、总结
如果需要确保代码块的原子性并且不关心线程是否能够在等待锁时被中断那么可以使用lock方法但是如果希望线程在等待锁时能够响应中断那么应该使用lockInterruptibly方法。在处理可能被中断的长时间操作或需要更细粒度的中断控制时lockInterruptibly通常是一个更好的选择。