이 기사에서는 주로 Java 동시 프로그래밍의 재진입 잠금 및 읽기-쓰기 잠금을 소개합니다. 기사의 관련 예제 코드는 상세하고 테스트에 사용할 수 있습니다. 필요한 친구는 더 자세히 알아볼 수 있습니다.
재진입 잠금
재진입 잠금은 이름에서 알 수 있듯이 재진입을 지원하는 잠금입니다. 이는 잠금이 스레드에 의한 리소스의 반복적인 잠금을 지원할 수 있음을 의미합니다. 재진입이란 잠금을 획득한 후 모든 스레드가 잠금에 의해 차단되지 않고 다시 잠금을 획득할 수 있음을 의미합니다.
1. 스레드가 다시 잠금을 획득합니다. 잠금은 잠금을 획득한 스레드가 현재 잠금을 점유하고 있는 스레드인지 식별해야 합니다. 그렇다면 다시 성공적으로 획득할 수 있습니다.
2. 최종 잠금 해제. 스레드는 n번 반복적으로 잠금을 획득하고 n번째 잠금을 해제한 후 다른 스레드가 잠금을 획득할 수 있습니다. 잠금을 최종 해제하려면 잠금을 획득하기 위한 횟수를 늘려야 합니다. 횟수는 현재 잠금이 반복적으로 획득된 횟수를 나타냅니다. 잠금이 해제되면 횟수가 0이 됩니다. 잠금이 성공적으로 해제되었습니다.
Java의 내장 잠금(동기화) 및 잠금(ReentrantLock)은 모두 재진입 가능
동기화 인스턴스
package com.home; public class SynchronizedTest implements Runnable { public synchronized void method1() { System.out.println("method1获得锁,正常运行!"); method2(); } public synchronized void method2() { System.out.println("method2获得锁,也正常运行!"); } @Override public void run() { method1(); } public static void main(String[] args) { SynchronizedTest st = new SynchronizedTest(); new Thread(st).start(); new Thread(st).start(); } }
잠금 인스턴스
package com.home; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockTest implements Runnable { Lock lock = new ReentrantLock(); public void method1() { lock.lock(); System.out.println("method1获得锁,正常运行!"); method2(); lock.unlock(); } public void method2() { lock.lock(); System.out.println("method2获得锁,也正常运行!"); lock.unlock(); } @Override public void run() { method1(); } public static void main(String[] args) { LockTest lt = new LockTest(); new Thread(lt).start(); new Thread(lt).start(); } }
예제의 최종 결과 모두 정확하며 결과는 다음과 같습니다.
method1获得锁,正常运行! method2获得锁,也正常运行! method1获得锁,正常运行! method2获得锁,也正常运行!
재진입 잠금의 가장 큰 역할은 교착 상태를 방지하는 것입니다
읽기-쓰기 잠금
읽기-쓰기 잠금은 한 쌍의 관련 잠금을 유지합니다. 하나는 읽기 작업 전용이고 다른 하나는 쓰기 작업 전용입니다. 작성기가 없는 한 읽기 잠금은 여러 판독기 스레드에 의해 동시에 유지될 수 있습니다. 쓰기 잠금은 배타적입니다.
Reentrant ReadWriteLock
ReentrantReadWriteLock 객체는 읽기 잠금 및 쓰기 잠금을 획득하기 위한 readLock() 및 writeLock() 메서드를 제공합니다.
읽기 잠금은 여러 판독기 스레드를 동시에 유지하며 쓰기를 허용합니다. 잠금은 최대 하나의 쓰기 스레드에서만 보유할 수 있습니다.
읽기-쓰기 잠금의 사용 사례: 공유 데이터를 읽는 빈도는 공유 데이터를 수정하는 빈도보다 훨씬 큽니다. 공유 리소스에 대한 액세스를 제어하고 동시성 성능을 향상시킬 수 있습니다.
스레드가 이미 쓰기 잠금을 보유하고 있다면 읽기-쓰기 잠금을 보유할 수 있습니다. 반대로 스레드가 이미 읽기 잠금을 보유하고 있다면 읽기 잠금이 해제되면 쓰기 잠금이 더 이상 유지될 수 없습니다.
쓰기 잠금에 바인딩된 Condition 개체를 얻기 위해 쓰기 잠금의 newCondition() 메서드를 호출할 수 있습니다. 차이점은 무엇입니까? 하지만 읽기 잠금의 newCondition() 메서드를 호출하면 예외가 발생합니다.
package com.home; import java.util.Random; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; class ReadWrte { // 共享数据,可以多个线程读数据,只能有一个线程写数据 private int data; // 创建读写锁 ReadWriteLock rwLock = new ReentrantReadWriteLock(); /** * 读数据,上读锁 */ public void get() { // 读锁 rwLock.readLock().lock(); try { System.out.println(Thread.currentThread().getName() + ",Read!"); Thread.sleep((long) Math.random() * 1000); System.out.println(Thread.currentThread().getName() + " 读出的数据为:" + this.getData()); } catch (Exception e) { e.printStackTrace(); } finally { rwLock.readLock().unlock(); } } /** * 写数据,上写锁 * * @param data */ public void put(int data) { // 写锁 rwLock.writeLock().lock(); try { System.out.println(Thread.currentThread().getName() + ",Write!"); Thread.sleep((long) Math.random() * 1000); this.setData(data); System.out.println(Thread.currentThread().getName() + " 写入的数据为:" + this.getData()); } catch (InterruptedException e) { e.printStackTrace(); } finally { rwLock.writeLock().unlock(); } } public int getData() { return data; } public void setData(int data) { this.data = data; } } /** * 测试类 * * @author itmyhome * */ public class ReadWriteLockTest { /** * @param args */ public static void main(String[] args) { // 创建ReadWrte对象 final ReadWrte rw = new ReadWrte(); for (int i = 0; i < 10; i++) { // 创建并启动10个读线程 new Thread(new Runnable() { @Override public void run() { rw.get(); } }).start(); // 创建并启动10个写线程 new Thread(new Runnable() { @Override public void run() { // 写入一个随机数 rw.put(new Random().nextInt(8)); } }).start(); } } }
출력은
Thread-0,Read! Thread-4,Read! Thread-8,Read! Thread-12,Read! Thread-0 读出的数据为:0 Thread-4 读出的数据为:0 Thread-8 读出的数据为:0 Thread-12 读出的数据为:0 Thread-19,Write! Thread-19 写入的数据为:5 Thread-7,Write! Thread-7 写入的数据为:7 Thread-3,Write! Thread-3 写入的数据为:4 Thread-16,Read! Thread-16 读出的数据为:4 Thread-11,Write! Thread-11 写入的数据为:0 Thread-15,Write! Thread-15 写入的数据为:5 Thread-2,Read! Thread-2 读出的数据为:5 Thread-17,Write! Thread-17 写入的数据为:2 Thread-6,Read! Thread-6 读出的数据为:2 Thread-1,Write! Thread-1 写入的数据为:5 Thread-13,Write! Thread-13 写入的数据为:4 Thread-9,Write! Thread-9 写入的数据为:7 Thread-5,Write! Thread-5 写入的数据为:2 Thread-10,Read! Thread-10 读出的数据为:2 Thread-18,Read! Thread-14,Read! Thread-18 读出的数据为:2 Thread-14 读出的数据为:2
입니다. 여러 스레드가 동시에 읽을 수 있지만 하나의 스레드만 쓸 수 있습니다. 즉, 데이터 쓰기와 데이터 쓰기가 동시에 완료됩니다.
위 내용은 Java 동시성의 재진입 잠금 및 읽기-쓰기 잠금에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!