你好,我刚接受电话采访我无法回答这个问题,我想知道答案,我相信,建议找到你不知道的答案。请鼓励我理解这个概念。
他的问题是:
“synchronized块只允许一个线程一次进入互斥部分。 当线程退出同步块时,同步块不指定 哪个等待线程将被允许进入互斥部分? 使用Object中提供的synchronized和方法,您可以先实现, 先服务互斥部分?保证线程被允许的一个 抵达顺序中的互斥部分? “
public class Test {
public static final Object obj = new Object();
public void doSomething() {
synchronized (obj) {
// mutual exclusive section
}
}
}
答案 0 :(得分:8)
这是一个简单的例子:
public class FairLock {
private int _nextNumber;
private int _curNumber;
public synchronized void lock() throws InterruptedException {
int myNumber = _nextNumber++;
while(myNumber != _curNumber) {
wait();
}
}
public synchronized void unlock() {
_curNumber++;
notifyAll();
}
}
你会像以下一样使用它:
public class Example {
private final FairLock _lock = new FairLock();
public void doSomething() {
_lock.lock();
try {
// do something mutually exclusive here ...
} finally {
_lock.unlock();
}
}
}
(注意,不会处理lock()调用者收到中断异常的情况!)
答案 1 :(得分:3)
他们所要求的是一个公平的互斥量
创建一个锁定对象的FIFO队列,由等待锁定的线程在其上推送,然后等待它(所有这些除了在单独的锁上的同步块中等待)
然后当释放锁时,会弹出一个对象队列,并且等待它的线程被唤醒(同样在同一个锁上同步以添加对象)
答案 2 :(得分:1)
您可以将ReentrantLock与fairness参数设置为true。然后服务的下一个线程将是等待最长时间的线程,即先到达的线程。
答案 3 :(得分:0)
这是我的尝试。为每个线程提供票号的想法。根据票号的顺序输入线程。我不熟悉Java,所以请阅读我的评论:
public class Test {
public static final Object obj = new Object();
unsigned int count = 0; // unsigned global int
unsigned int next = 0; // unsigned global int
public void doSomething() {
unsigned int my_number; // my ticket number
// the critical section is small. Just pick your ticket number. Guarantee FIFO
synchronized (obj) { my_number = count ++; }
// busy waiting
while (next != my_number);
// mutual exclusion
next++; // only one thread will modify this global variable
}
}
这个答案的缺点是忙碌的等待会消耗CPU时间。
答案 4 :(得分:0)
仅使用Object的方法和synchronized,在我看来有点困难。也许,通过设置每个线程的优先级,您可以保证对关键部分的有序访问。