powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Изучаю, появляются вопросы
4 сообщений из 4, страница 1 из 1
Изучаю, появляются вопросы
    #39380645
Shr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Читаю пока книжку "Герберт Шилдт. Java 8. Полное руководство. Девятое издание".

Первый вопрос. Вот код (со страницы 307), он вроде работает:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
class Q {
  private int v;
  private boolean valueSet = false;
  
  synchronized public void put(int v) {
    while (valueSet) 
      try {
        wait();
      }
      catch (InterruptedException e)  {
        System.out.println("interrupted in Q.put()");
        return;
      }
    this.v = v;
    valueSet = true;
    System.out.println("put " + v);
    notify();
  }
  
  synchronized public int get() {
    while (!valueSet)
      try {
        wait();
      }
      catch (InterruptedException e)  {
        System.out.println("interrupted in Q.get()");
        return 0;
      }
    valueSet = false;
    notify();
    return v;
  }
}

class Producer implements Runnable {
  private Q q;
  
  Producer(String name,Q q) {
    this.q = q;
    new Thread(this, name).start();
  }
  
  public void run() {
    for (int i = 0; i <= 10; i++) {
      q.put(i);
    }
  }
}

class Consumer implements Runnable {
  private Q q;
  
  Consumer(String threadName, Q q) {
    this.q = q;
    new Thread(this, threadName).start();
  }
  
  public void run() {
    while (true) {
      System.out.println("consumer got " + q.get());
    }
  }
}

class Main {
  public static void main(String[] args) {
    Q q = new Q();
    new Producer("producer", q);
    new Consumer("consumer", q);
  }
}



Вопрос 1. Может ли между операторами строк 30 и 31 измениться значение this.v? Значит ли это что надо завести копию в локальной переменной до вызова notify() и возвращать её?
Вопрос 2. Что если в классе у меня есть несколько полей доступ к которым надо разделять отдельно (в golang для этого я бы использовал мутексы с разным именем)? Как в java поступают в таком случае? Заводят отдельный класс и делают уже его полем-хранителем нужных данных, и монитор (wait-notify) работает в рамках этого отдельного экземпляра?
...
Рейтинг: 0 / 0
Изучаю, появляются вопросы
    #39380651
Andrew1411
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shr,

1. пока ваш монитор занят (не вышли из синхронайза, либо не выполнили wait) - никто в него не зайдет, но никто не помешает изменить поле без синхронизации (про видимость изменений говорить не будем)
2. Синхронизироваться можно не только на this, можно завести отдельные мониторы и синхронизировать по ним блоки кода (а не методы)

Кроме того, когда у вас монитор публичный, то его может заблокировать любой (без рефлексии) - и у вас все остановится.
Так же, в этом случае, ваш notify может "проглотить" чужой код - как говорят - не уверен - поставь notifyAll (ухудшается производительность, но уведомление не потеряется)
...
Рейтинг: 0 / 0
Изучаю, появляются вопросы
    #39380660
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShrВопрос 1. Может ли между операторами строк 30 и 31 измениться значение this.v? Значит ли это что надо завести копию в локальной переменной до вызова notify() и возвращать её?

Нет. Ведь модификация происходит только в synchronized методе, и строки 30, 31 тоже синхронизированы по тому же мутексу.

ShrВопрос 2. Что если в классе у меня есть несколько полей доступ к которым надо разделять отдельно (в golang для этого я бы использовал мутексы с разным именем)? Как в java поступают в таком случае? Заводят отдельный класс и делают уже его полем-хранителем нужных данных, и монитор (wait-notify) работает в рамках этого отдельного экземпляра?

synchronized метод это аналог такого кода:
Код: java
1.
2.
3.
4.
5.
void methodName(){
    synchronized(this){
          ...
    }
}


В Java любой объект может быть мутексом. Соответственно можно делать так:
Код: java
1.
2.
3.
4.
5.
6.
private final Object LOCK = new Object();
void methodName(){
    synchronized(LOCK){
          ...
    }
}



Но, если нужны какие-либо изыски, то synchronized, обычно, идёт лесом, так как есть Java Concurrent Utils.
...
Рейтинг: 0 / 0
Изучаю, появляются вопросы
    #39380767
Shr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо, понятно.
С приватным монитором должно быть где-то так?

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
class Q {
  private int v;
  private boolean valueSet = false;
  private final Object lockV = new Object();
  
  public void put(int v) {
    synchronized(lockV) {
      while (valueSet) 
        try {
          lockV.wait();
        }
        catch (InterruptedException e)  {
          System.out.println("interrupted in Q.put()");
          return;
        }
      this.v = v;
      valueSet = true;
      lockV.notify();
    }
  }
  
  public int get() {
    synchronized(lockV) {
      while (!valueSet)
        try {
          lockV.wait();
        }
        catch (InterruptedException e)  {
          System.out.println("interrupted in Q.get()");
          return 0;
        }
      valueSet = false;
      lockV.notify();
      return v;
    }
  }
}
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Изучаю, появляются вопросы
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]