Дэвид, Шон и Фрэнк постоянно сажают семена. Дэвид роет ямы. Затем Шон
кладет по семечку в каждую лунку. Затем Фрэнк заполняет дыру. Существует несколько
ограничений синхронизации:
- Шон не может посадить семя, если не существует хотя бы одной пустой лунки, но Шон это делает
не важно, насколько Дэвид опережает Шона. - Фрэнк не может заполнить дыру, если не существует хотя бы одной дыры, в которой Шон имеет успех
посадил семя, но ямка еще не засыпана. Фрэнка не волнует, насколько
далеко Шон опередит Фрэнка. - Фрэнка волнует, что Дэвид не забивает больше MAX лунок впереди
Фрэнка. Таким образом, если незаполненных ям МАКСИМАЛЬНО, Дэвиду придется подождать. - Есть только одна лопата, которой Дэвиду и Фрэнку нужно копать. и заполните
дыры соответственно.
использовал семафоры в качестве механизма синхронизации. Обязательно инициализируйте
семафоры.
И это мое решение, реализованное на Java, которое, я знаю, не очень элегантное и своего рода расточительно по сравнению со стандартным решением:
Код: Выделить всё
import java.util.concurrent.Semaphore;
public class Holes {
private static final int MAX = 3;
private static final Semaphore mutexForShovel = new Semaphore(1, true);
private static final Semaphore mutexForHoleCount = new Semaphore(1, true);
private static int emptyHoleCount = 0, seededHoleCount = 0, finishedHoleCount = 0;
public static void main(String[] args) {
new Thread(() -> { // David
try {
while (true) {
if (emptyHoleCount < MAX) {
mutexForShovel.acquire(); // wait for shovel
System.out.println("David is digging a hole...");
Thread.sleep(200); // try annotating this
mutexForShovel.release(); // release shovel
mutexForHoleCount.acquire(); // enter critical section
emptyHoleCount++;
mutexForHoleCount.release(); // exit critical section
System.out.println("Empty = " + emptyHoleCount +
" Seeded = " + seededHoleCount +
" Finished = " + finishedHoleCount);
}
}
} catch (InterruptedException e) {
System.out.println(e.toString());
}
}).start();
new Thread(() -> { // Sean
while (true) {
try {
if (emptyHoleCount > 0) {
System.out.println("Sean is seeding a hole...");
Thread.sleep(200); // try annotating this
mutexForHoleCount.acquire(); // enter critical section
emptyHoleCount--;
seededHoleCount++;
mutexForHoleCount.release(); // exit critical section
System.out.println("Empty = " + emptyHoleCount +
" Seeded = " + seededHoleCount +
" Finished = " + finishedHoleCount);
}
} catch (InterruptedException e) {
System.out.println(e.toString());
}
}
}).start();
new Thread(() -> { // Frank
while (true) {
try {
if (seededHoleCount > 0) {
mutexForShovel.acquire(); // ask for shovel
System.out.println("Frank is filling a hole...");
Thread.sleep(200); // try annotating this
mutexForShovel.release(); // release shovel
mutexForHoleCount.acquire(); // enter critical section
seededHoleCount--;
finishedHoleCount++;
mutexForHoleCount.release(); // exit critical section
System.out.println("Empty = " + emptyHoleCount +
" Seeded = " + seededHoleCount +
" Finished = " + finishedHoleCount);
}
} catch (InterruptedException e) {
System.out.println(e.toString());
}
}
}).start();
}
}
Код: Выделить всё
David is digging a hole...
Empty = 1 Seeded = 0 Finished = 0
David is digging a hole...
Empty = 2 Seeded = 0 Finished = 0
David is digging a hole...
Empty = 3 Seeded = 0 Finished = 0
Код: Выделить всё
David is digging a hole...
Sean is seeding a hole...
Frank is filling a hole...
Empty = 1 Seeded = 0 Finished = 0
Empty = 0 Seeded = 1 Finished = 0
David is digging a hole...
Empty = 1 Seeded = 0 Finished = 1
Sean is seeding a hole...
David is digging a hole...
Empty = 0 Seeded = 0 Finished = 1
Empty = 0 Seeded = 1 Finished = 1
Frank is filling a hole...
Empty = 1 Seeded = 1 Finished = 1
Empty = 1 Seeded = 0 Finished = 2
Sean is seeding a hole...
David is digging a hole...
...
Код: Выделить всё
...
Sean is seeding a hole...
Frank is filling a hole...
Empty = 2 Seeded = 0 Finished = 29748
Empty = 2 Seeded = 1 Finished = 29747
Sean is seeding a hole...
Frank is filling a hole...
Empty = 1 Seeded = 1 Finished = 29748
Empty = 1 Seeded = 0 Finished = 29749
Sean is seeding a hole...
Frank is filling a hole...
Empty = 0 Seeded = 1 Finished = 29749
Empty = 0 Seeded = 0 Finished = 29750
Process finished with exit code 130 (interrupted by signal 2: SIGINT)
Поэтому у меня теперь два вопроса:
Вопрос 1. Предполагает ли исходный вывод терминала, что произошла взаимоблокировка? Если да, то какая часть моего кода неверна и как я могу ее изменить?
Вопрос 2. Почему я получаю разные результаты при запуске один и тот же код по-разному?
Большое спасибо!!!
Подробнее здесь: https://stackoverflow.com/questions/655 ... semaphores