繁体   English   中英

Java多线程获取锁不起作用

[英]java multi-thread acquire lock not working

我正在尝试编写一小段代码以锁定和解锁代码块。 Acquisition_lock和release_lock函数如下:

    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函数不能正常工作。 似乎最后两个线程(撤回500和撤回1000)已经同时进入了Acquisition_lock()和release_lock()之间的块,这不是我想要的。 那么acquire_lock和release_lock函数怎么了?

这里非常棘手。 发生异常是因为后面的线程首先进入了acquire_lock。 并且当较早的线程进入acquired_lock时,它将不会被阻塞,因为代码会根据其时间戳来阻塞线程。 因此,这两个线程转到相同的受保护代码区域。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM