자바 의 잠 금 분류 및 사용 방법
자 물 쇠 는 공유 자원 에 대한 접근 을 제어 하 는 도구 이다
주요 방법
Lock();
가장 일반적인 자 물 쇠 를 얻 습 니 다.가장 좋 은 실천 은 finally 에서 자 물 쇠 를 방출 하 는 것 입 니 다.이상 이 발생 할 때 자 물 쇠 는 반드시 방출 됩 니 다.
/**
* :Lock syn ,
* finally ,
*/
private static Lock lock = new ReentrantLock();
public static void main(String[] args) {
lock.lock();
try {
//
System.out.println(Thread.currentThread().getName() + " ");
} finally {
lock.unlock();
}
}
tryLock(long time,TimeUnit unit);시간 을 초과 하면 포기 하 다.자 물 쇠 를 가 져 오 는 데 사용 합 니 다.현재 자물쇠 가 다른 스 레 드 에 점용 되 지 않 으 면 성공 을 가 져 오 면 true 로 돌아 갑 니 다.그렇지 않 으 면 false 로 돌아 가 자 물 쇠 를 가 져 오 는 데 실 패 했 습 니 다.
/**
* : TryLock
*/
static class TryLockDeadlock implements Runnable {
int flag = 1;
static Lock lock1 = new ReentrantLock();
static Lock lock2 = new ReentrantLock();
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (flag == 1) {
try {
if (lock1.tryLock(800, TimeUnit.MILLISECONDS)) {
try {
System.out.println(" 1 1");
Thread.sleep(new Random().nextInt(1000));
if (lock2.tryLock(800,TimeUnit.MILLISECONDS)){
try {
System.out.println(" 1 2");
System.out.println(" 1 2 ");
break;
}finally {
lock2.unlock();
}
}else{
System.out.println(" 1 2 , ");
}
} finally {
lock1.unlock();
Thread.sleep(new Random().nextInt(1000));
}
} else {
System.out.println(" 1 1 , ");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (flag == 0) {
try {
if (lock2.tryLock(3000, TimeUnit.MILLISECONDS)) {
try {
System.out.println(" 2 2");
Thread.sleep(new Random().nextInt(1000));
if (lock1.tryLock(800,TimeUnit.MILLISECONDS)){
try {
System.out.println(" 2 1");
System.out.println(" 2 2 ");
break;
}finally {
lock1.unlock();
}
}else{
System.out.println(" 2 1 , ");
}
} finally {
lock2.unlock();
Thread.sleep(new Random().nextInt(1000));
}
} else {
System.out.println(" 2 2 , ");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
TryLockDeadlock r1 = new TryLockDeadlock();
TryLockDeadlock r2 = new TryLockDeadlock();
r1.flag = 1;
r2.flag = 0;
new Thread(r1).start();
new Thread(r2).start();
}
}
:
1 1
2 2
1 2 ,
2 1
2 2
1 1
1 2
1 2
lockInterruptibly(); 인 터 럽 트tryLock(long time,TimeUnit unit)이 시간 초과 시간 을 무한 으로 설정 한 것 과 같 습 니 다.잠 금 을 기다 리 는 과정 에서 스 레 드 가 중 단 될 수 있 습 니 다.
/**
* : ,
*/
static class LockInterruptibly implements Runnable {
private Lock lock = new ReentrantLock();
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " ");
try {
lock.lockInterruptibly();
try {
System.out.println(Thread.currentThread().getName() + " ");
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " ");
} finally {
lock.unlock();
System.out.println(Thread.currentThread().getName() + " ");
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " ");
}
}
public static void main(String[] args) {
LockInterruptibly lockInterruptibly = new LockInterruptibly();
Thread thread0 = new Thread(lockInterruptibly);
Thread thread1 = new Thread(lockInterruptibly);
thread0.start();
thread1.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread0.interrupt();
}
}
:
Thread-0
Thread-1
Thread-0
Thread-0
Thread-0
Thread-1
Thread-1
Java 잠 금 분류:낙관적 자물쇠 와 비관 적 자물쇠:
낙관적 자물쇠:
비교적 낙관적 이 고 자신 이 조작 을 처리 할 때 다른 스 레 드 가 방해 되 지 않 을 것 이 라 고 생각 하기 때문에 조작 대상 을 잠 그 지 않 습 니 다.
4.567917.업데이트 할 때 제 가 수정 한 동안 의 데이터 가 바 뀌 었 는 지 비교 해 보 세 요.없 으 면 정상 적 인 수정 데이터 입 니 다4.567917.만약 에 데이터 가 제 가 처음에 받 은 것 과 다 르 면 다른 사람들 이 이 시간 안에 잘못 을 고치 면 포기,잘못 보고,재 시도 등 전략 을 선택 할 것 입 니 다4.567917.낙관적 인 자물쇠 의 실현 은 일반적으로 CAS 알고리즘 을 이용 하여 이 루어 진다.
열세:
ABA 문 제 를 일 으 킬 수 있 지만 수정 한 건 지 모 르 겠 어 요.
사용 필드:
동시 쓰기 가 적은 경우 에 적합 합 니 다.대부분 읽 는 장면 입 니 다.잠 금 을 넣 지 않 으 면 읽 을 수 있 는 성능 이 크게 향상 되 었 습 니 다.
비관 자물쇠:
비관 적 입 니 다.만약 에 제 가 이 자원 을 잠 그 지 않 으 면 다른 사람 이 다 투 게 되 고 데이터 결과 가 잘못 되 기 때문에 조작 대상 을 잠 글 것 이 라 고 생각 합 니 다.자바 에서 비관 적 인 자물쇠 의 실현 은 바로 syn 과 Lock 관련 유형 입 니 다.
열세:
4.567917.차단 과 각성 이 가 져 온 성능 약점4.567917.자 물 쇠 를 가 진 스 레 드 가 영구적 으로 막 히 면 예 를 들 어 무한 순환,자물쇠 잠 금 등 활성 문제 에 부 딪 히 면 이 스 레 드 가 자 물 쇠 를 풀 어 주 기 를 기다 리 는 몇 개의 스 레 드 는 영원히 실 행 될 수 없다4.567917.우선 순위 반전,우선 순위 가 낮은 스 레 드 가 자 물 쇠 를 가 져 오 거나 풀 리 지 않 는 것 이 비교적 느 리 면 이 문 제 를 초래 할 수 있다.
사용 필드:
동시 다발 기록 이 많은 경우 에 적합 하 며 임계 구역 의 잠 금 시간 이 비교적 긴 경우 에 적 용 됩 니 다.
임계 구역 에 IO 조작 이 있 습 니 다임계 구역 코드 가 복잡 하거나 순환 량 이 크다임계 지역 의 경쟁 이 매우 치열 하 다.
재 접속 가능 한 자물쇠:
다시 들 어 갈 수 있다 는 것 은 어떤 스 레 드 가 이미 어떤 자 물 쇠 를 얻 었 기 때문에 자물쇠 가 생기 지 않 고 다시 자 물 쇠 를 얻 을 수 있다 는 것 이다.
ReentrantLock 과... synchronized 는 모두 잠 금 을 다시 넣 을 수 있 습 니 다.
//
static class RecursionDemo{
public static ReentrantLock lock = new ReentrantLock();
private static void accessResource(){
lock.lock();
try {
System.out.println(" ");
if (lock.getHoldCount() < 5){
System.out.println(" "+lock.getHoldCount()+" ");
accessResource();
}
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
new RecursionDemo().accessResource();
}
}
:
1
2
3
4
ReentrantLock 의 다른 방법4.567917.공평 이란 스 레 드 가 요구 하 는 순서에 따라 자 물 쇠 를 분배 하 는 것 을 말한다4
/**
* :
*/
class FairLock{
public static void main(String[] args) {
PrintQueue printQueue = new PrintQueue();
Thread[] thread = new Thread[10];
for (int i = 0; i < 10; i++) {
thread[i] = new Thread(new Job(printQueue));
}
for (int i = 0; i < 5; i++) {
thread[i].start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Job implements Runnable{
PrintQueue printQueue;
public Job(PrintQueue printQueue) {
this.printQueue = printQueue;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" ");
printQueue.printJob(new Object());
System.out.println(Thread.currentThread().getName()+" ");
}
}
class PrintQueue{
// true ,false
private Lock queueLock = new ReentrantLock(true);
public void printJob(Object document){
queueLock.lock();
try {
int duration = new Random().nextInt(10)+1;
System.out.println(Thread.currentThread().getName()+" , "+duration+" ");
Thread.sleep(duration * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
queueLock.unlock();
}
queueLock.lock();
try {
int duration = new Random().nextInt(10)+1;
System.out.println(Thread.currentThread().getName()+" , "+duration+" ");
Thread.sleep(duration * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
queueLock.unlock();
}
}
}
:
Thread-0
Thread-0 , 10
Thread-1
Thread-2
Thread-3
Thread-4
Thread-1 , 2
Thread-2 , 2
Thread-3 , 2
Thread-4 , 4
Thread-0 , 2
Thread-0
Thread-1 , 7
Thread-1
Thread-2 , 8
Thread-2
Thread-3 , 3
Thread-3
Thread-4 , 8
Thread-4
true false :
Lock queueLock = new ReentrantLock(false);
:
Thread-0 , 7
Thread-1
Thread-2
Thread-3
Thread-4
Thread-0 , 9
Thread-0
Thread-1 , 3
Thread-1 , 2
Thread-1
Thread-2 , 4
Thread-2 , 7
Thread-2
Thread-3 , 10
Thread-3 , 2
Thread-3
Thread-4 , 7
Thread-4 , 8
Thread-4
공유 자물쇠 와 열 쇠:4.567917.배타 적 자 물 쇠 는 독점 자물쇠 라 고도 부 르 는데 독점 자물쇠4.567917.공유 자 물 쇠 는 읽 기 자물쇠 라 고도 부 릅 니 다.공유 자 물 쇠 를 얻 은 후에 데 이 터 를 볼 수 있 지만 수정 하고 삭제 할 수 없습니다.다른 스 레 드 는 이때 도 공유 자 물 쇠 를 얻 을 수 있 고 볼 수 있 지만 데 이 터 를 수정 하고 삭제 할 수 없습니다4.567917.공유 자물쇠 와 배타 자물쇠 의 전형 은 읽 기와 쓰기 자물쇠 이다. ReentrantReadWriteLock,읽 기 자 물 쇠 는 공유 자물쇠,쓰기 자 물 쇠 는 독점 자물쇠
읽 기와 쓰기 자물쇠 의 역할:
4.567917.읽 기와 쓰기 자물쇠 가 없 기 전에 우 리 는 ReentrantLock 을 사용한다 고 가정 합 니 다.그러면 우 리 는 스 레 드 안전 을 보장 하지만 일정한 자원 도 낭비 합 니 다.여러 개의 읽 기 작업 을 동시에 진행 하고 스 레 드 안전 문제 가 없습니다읽 는 곳 에서 읽 기 자 물 쇠 를 사용 하고 쓰 는 곳 에서 쓰기 자 물 쇠 를 사용 하여 유연 하 게 제어 한다.만약 에 자 물 쇠 를 쓰 지 않 은 상황 에서 읽 기 는 막힘 이 없고 프로그램의 집행 효율 을 높 인 다.
자물쇠 읽 기 규칙:
4.567917.여러 개의 스 레 드 값 이 읽 기 자 물 쇠 를 신청 하면 모두 4.567918 에 신청 할 수 있 습 니 다.
4
/**
* : ,
*/
class CinemaReadWrite{
private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
private static ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
private static ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();
private static void read(){
readLock.lock();
try {
System.out.println(Thread.currentThread().getName() + " , ");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + " ");
readLock.unlock();
}
}
private static void write(){
writeLock.lock();
try {
System.out.println(Thread.currentThread().getName() + " , ");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + " ");
writeLock.unlock();
}
}
public static void main(String[] args) {
new Thread(()-> read(),"Thrad1").start();
new Thread(()-> read(),"Thrad2").start();
new Thread(()-> write(),"Thrad3").start();
new Thread(()-> write(),"Thrad4").start();
}
}
:
Thrad1 ,
Thrad2 ,
Thrad2
Thrad1
Thrad3 ,
Thrad3
Thrad4 ,
Thrad4
읽 기와 쓰기 자물쇠 의 대화 방식:읽 기 삽입 정책:
공평 자물쇠:새치기 불가4
4.567917.현재 스 레 드 를 자전 시 킵 니 다.자전 이 완 료 된 후에 앞 에 동기 화 자원 을 잠 그 는 스 레 드 가 잠 겨 있 으 면 현재 스 레 드 는 막 지 않 고 동기 화 자원 을 직접 가 져 와 스 레 드 전환 비용 을 피 할 수 있 습 니 다.이것 이 바로 자전거 자물쇠 다4.567917.자 물 쇠 를 막 는 것 은 자전 자물쇠 와 반대로 자 물 쇠 를 막 는 것 은 자 물 쇠 를 얻 지 못 한 상황 이 발생 하면 바로 스 레 드 를 막 고 깨 워 진 것 을 알 게 된다.
자전 단점:
4.567917.잠 금 이 오래 걸 리 면 자전 하 는 스 레 드 는 프로세서 자원 을 낭비 할 뿐이다4.567917.자전 하 는 과정 에서 cpu 를 계속 소모 하기 때문에 자전 자물쇠 의 시작 비용 은 비관 적 인 자물쇠 보다 낮 지만 자전 하 는 시간 이 증가 함 에 따라 비용 도 선형 으로 증가 했다.
원리:
4.567917.자바 1.5 버 전 및 이상 의 병발 프레임 워 크 자바 util.concurrent 의 atmoic 패키지 의 종 류 는 기본적으로 자전 자물쇠 의 실현 이다4
/**
* :
*/
class SpinLock{
private AtomicReference<Thread> sign = new AtomicReference<>();
public void lock(){
Thread currentThread = Thread.currentThread();
while (!sign.compareAndSet(null,currentThread)){
System.out.println(" , ");
}
}
public void unLock(){
Thread currentThread = Thread.currentThread();
sign.compareAndSet(currentThread,null);
}
public static void main(String[] args) {
SpinLock spinLock = new SpinLock();
Runnable runnable = new Runnable(){
@Override
public void run(){
System.out.println(Thread.currentThread().getName()+" ");
spinLock.lock();
System.out.println(Thread.currentThread().getName()+" ");
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
spinLock.unLock();
System.out.println(Thread.currentThread().getName()+" ");
}
}
};
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
thread1.start();
thread2.start();
}
}
:
Thread-0
Thread-0
Thread-1
,
,
,
,
,
,
,
,
,
,
,
Thread-0
Thread-1
Thread-1
사용 필드:4.567917.자전 자 물 쇠 는 보통 다 핵 서버 에 사용 되 는데 병발 도가 특별히 높 지 않 은 상황 에서 자 물 쇠 를 막 는 효율 보다 높다4.567917.또한 자 회전 자 물 쇠 는 임계 구역 이 비교적 짧 은 상황 에 적용 된다.그렇지 않 으 면 임계 구역 이 매우 크다(스 레 드 가 자 물 쇠 를 가 져 오 면 오래 후에 방출 된다).그것 도 적당 하지 않다.
총결산
자바 의 잠 금 분류 와 사용 방법 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 자바 의 잠 금 사용 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.