코드 블록을 잠 그거나 잠금 해제하는 작은 스 니펫을 작성하려고합니다. acquire_lock와 RELEASE_LOCK 기능은 다음과 같습니다 :java 멀티 스레드 획득 잠금이 작동하지 않습니다.
public static void acquire_lock(long timestamp) {
synchronized(operations) {
// put the timestamp into queue
operations.add(timestamp);
// check if the head of queue is current timestamp, if not,
// this means there are some other operations ahead of current one
// so current operation has to wait
while (operations.peek() != timestamp) {
try {
operations.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void release_lock() {
synchronized(operations) {
// poll the finished operation out of queue
// and wake up all waiting operations
operations.poll();
operations.notifyAll();
}
}
을하지만 테스트 환경에이 코드를 삽입 할 때, 항상 잘 작동하지 않습니다, 전체 테스트 코드는 다음과 같습니다 :
public class AcquireLockNotWork {
static int balance = 0;
static PriorityQueue<Long> operations = new PriorityQueue<Long>();
// withdraw money from balance
public static void withdraw(final int amt) {
// get system time
Long timestamp = System.nanoTime();
Thread t = new Thread(new Runnable() {
public void run() {
// try to use acquire_lock to lock this piece of code
acquire_lock(timestamp);
try {
Thread.sleep(500);
int holdings = balance;
balance = holdings - amt;
System.out.println("Withdrew " + amt + " from funds. Now at " + balance);
} catch (Exception e) {
e.printStackTrace();
} finally {
release_lock();
}
}
});
t.start();
}
//put money into banlance
public static void deposit(int amt) {
Thread t1 = new Thread(new Runnable() {
public void run() {
Long timestamp = System.nanoTime();
acquire_lock(timestamp);
int holdings = balance;
balance = holdings + amt;
System.out.println("deposit " + amt + ", balance: " + balance);
release_lock();
}
});
t1.start();
}
public static void acquire_lock(long timestamp) {
synchronized(operations) {
// put the timestamp into queue
operations.add(timestamp);
// check if the head of queue is current timestamp, if not,
// this means there are some other operations ahead of current one
// so current operation has to wait
while (operations.peek() != timestamp) {
try {
operations.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void release_lock() {
synchronized(operations) {
// poll the finished operation out of queue
// and wake up all waiting operations
operations.poll();
operations.notifyAll();
}
}
public static void test1() {
balance = 0;
deposit(2000);
withdraw(500);
withdraw(1000);
}
public static void main(String[] args) {
test1();
}
}
작은 횟수 대
이 결과는 다음과 같을 것이다 :
deposit 2000, balance: 2000
Withdrew 500 from funds. Now at 500
Withdrew 1000 from funds. Now at 500
acquire_lock 및 RELEASE_LOCK 푸 즉 의무가 잘 작동하지 않습니다. 마지막 2 개의 스레드 (withdrew 500 및 withdru 1000)가 acquire_lock()과 release_lock() 사이의 블록에 동시에 들어갔고, 원하는 것이 아닌 것으로 보입니다. acquire_lock 및 release_lock 함수의 문제점은 무엇입니까?
코드가 동일한 값을 두 번 이상 반환하지 않는 System.nanoTime()에 의존하는 것으로 보이지만 그 동작은 보장되지 않습니다. System.nanoTime()의 Javadoc은 "이 메서드는 나노초 정밀도를 제공하지만 반드시 나노초 해상도 (즉, 값 변경 빈도)가 아닙니다"라고 말합니다. –