자물쇠 및 synchronized
자물쇠의 흔한 개념
자물쇠로 하는 최고의 실천
동기식 및 비동기식
비동기식 프로그램을 지원하는 방법:
synchronized
class X{
//
synchronized void foo(){
//
}
//
synchronized static void bar(){
//
}
//
Object obj = new Object();
void baz(){
synchronized(obj){
//
}
}
}
자바 컴파일러는synchronized에서 수식하는 방법이나 코드 블록의 앞뒤에 자동으로 잠금lock()과 잠금해제unlock()를 추가합니다. 이렇게 하는 장점은 잠금해제()와 잠금해제unlock()는 틀림없이 쌍을 이루고 나타날 것입니다. 잠금해제unlock()는 치명적인 Bug(다른 라인은 죽을 수밖에 없다는 것을 의미합니다.)
코스메틱 정적 방법:
//
class X{
//
synchronized(X.class) static void bar(){
//
}
}
코스메틱 고정되지 않은 방법:
//
class X{
//
synchronized(this) static void bar(){
//
}
}
어떻게 자물쇠로 여러 자원을 보호합니까
보호된 자원과 자물쇠 사이의 합리적인 관련 관계는 N:1의 관계이다. 즉, 한 개의 자물쇠로 여러 자원을 보호할 수 있지만 여러 개의 자물쇠로 한 자원을 보호할 수 없다.
자물쇠를 사용하는 정확한 자세
이체 업무를 예로 들다
예 1:
public class Account {
/**
* :
*/
private final Object balLock = new Object();
/**
*
*/
private Integer balance;
/**
*
* this,
* this this.balance, target.balance
*
*/
synchronized void transfer(Account target,int amt){
if (this.balance > amt) {
this.balance -= amt;
target.balance += amt;// ,
}
}
}
예 2:
public class Account {
/**
* :
*/
private final Object balLock = new Object();
/**
*
*/
private Integer balance;
/**
* ,
*
* Account.class Account ,
* Java Account ,
*
*
* :
*/
void transfer2(Account target,int amt){
synchronized(Account.class){
if (this.balance > amt) {
this.balance -= amt;
target.balance += amt;
}
}
}
}
이렇게 하면 이체 조작은 직렬이 되고 정상적인 논리는 계좌 이체와 계좌 이체만 잠궈야 한다.다른 이체 작업에 영향을 주지 않습니다.약간의 변경 사항:
예 3:
public class Account {
/**
* :
*/
private final Object lock;
/**
*
*/
private Integer balance;
//
private Account(){}
// lock
private Account(Object lock){
this.lock = lock;
}
/**
*
*/
void transfer(Account target,int amt){
//
synchronized(lock){
if (this.balance > amt) {
this.balance -= amt;
target.balance += amt;
}
}
}
}
이 방법은 문제를 해결할 수 있지만, Account 대상을 만들 때 같은 대상에게 전송해야 합니다.
그리고 전달 대상이 너무 번거롭고 쓰기가 번거로워 타당성이 부족하다.
예 4:
public class Account {
/**
*
*/
private Integer balance;
/**
*
*/
void transfer(Account target,int amt){
//
synchronized(Account.class){
if (this.balance > amt) {
this.balance -= amt;
target.balance += amt;
}
}
}
}
어카운트로.class는 공유된 자물쇠로서 잠긴 범위가 너무 넓습니다.Account.class는 모든 계정 대상이 공유하고, 이 대상은 자바 가상기가 계정 클래스를 불러올 때 만든 것이기 때문에 유일성을 걱정할 필요가 없습니다.Account을 사용합니다.class는 공유 자물쇠로서 계정 대상을 만들 때 전송할 필요가 없습니다.
이렇게 새로운 문제가 생겼어요. 어카운트를 쓰지만.class는 상호 배척 자물쇠로서 은행 업무 중의 이체 문제를 해결한다. 이 방안은 병발 문제가 존재하지 않지만 모든 계좌의 이체 조작은 직렬이다. 예를 들어 계좌 A이체 계좌 B, 계좌 C이체 계좌 D 두 이체 조작은 현실 세계에서 병행할 수 있지만 이 방안에서 직렬화되었다. 이렇게 하면 성능이 너무 떨어진다.그래서 병발량을 생각하면 이런 방법도 안 돼요.
올바른 쓰기 방법은 다음과 같습니다.
예 5:
public class Account {
/**
*
*/
private Integer balance;
/**
*
*/
void transfer(Account target,int amt){
//
synchronized(this){
//
synchronized(target){
if (this.balance > amt) {
this.balance -= amt;
target.balance += amt;
}
}
}
}
}
우리는 고대에 정보화가 없으면 계좌의 존재 형식이 정말 하나의 장부였고 모든 계좌에 하나의 장부가 있었으며 이런 장부들은 모두 서류함에 통일적으로 보관되었다고 생각해 보았다.은행 카운터는 우리에게 이체를 할 때 서류함에 가서 이체 장부와 이체 장부를 모두 손에 넣은 후에 이체를 해야 한다.이 점원은 장부를 가져올 때 다음과 같은 세 가지 상황을 만날 수 있다.
세립도 자물쇠가 사라질 수도 있어요.
어떻게 하면 자물쇠가 사라지는 것을 피할 수 있습니까
그중의 하나만 파괴하면 자물쇠가 사라지는 것을 피할 수 있다
대기 - 알림 메커니즘
synchronized로 대기 - 알림 메커니즘 구현
wait와 sleep의 차이점:
sleep은 Object의 메서드이고 wait는 Thread의 메서드입니다.
wait 자물쇠 방출,sleep 자물쇠 방출
wait는 notif로 깨우고, sleep로 시간을 설정해야 합니다. 시간이 되면 깨우기
wait 이상 포획 필요 없음,sleep 필요
wait (): 현재 스레드가 막혔습니다
****문자가 쉽지 않으니 도움이 되시면 팔로우 주세요****
****애기술애생활QQ군:894109590***
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.