Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / synchronized / 3 сообщений из 3, страница 1 из 1
13.04.2005, 09:48
    #33012380
Новичек 2
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
synchronized
Добрый день. Яву изучаю недавно. Поэтому еще не все понимаю.
Вот попался мне пример из книжки.


Код: plaintext
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.
 package  com.jspbook;

 import  java.util.*;
 import  java.io.*;
 import  javax.servlet.*;
 import  javax.servlet.http.*;

 public   class  LinkTracker  extends  HttpServlet {
   static   private  Hashtable links =  new  Hashtable();

  String tstamp;
   public  LinkTracker() {
    tstamp =  new  Date().toString();
  }

   public   void  doGet(HttpServletRequest request,
                    HttpServletResponse response)
     throws  IOException, ServletException {

    String link = request.getParameter("link");
     if  (link !=  null  && !link.equals("")) {
       synchronized  (links){
        Integer count = (Integer) links.get(link);
         if  (count ==  null ) {
          links.put(link,  new  Integer( 1 ));
        }
         else  {
          links.put(link,  new  Integer( 1 +count.intValue()));
        }
      }
      response.sendRedirect(link);
    }
     else  {
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();
      request.getSession();
      out.println("<html>");
      out.println("<head>");
      out.println("<title>Links Tracker Servlet</title>");
      out.println("</head>");
      out.println("<body>");
      out.println("<p>Links Tracked Since");
      out.println(tstamp+":</p>");
       if  (links.size() !=  0 ) {
        Enumeration enum = links.keys();
         while  (enum.hasMoreElements()) {
          String key = (String)enum.nextElement();
           int  count = ((Integer)links.get(key)).intValue();
          out.println(key+" : "+count+" visits<br>");
        }
      }
       else  {
        out.println("No links have been tracked!<br>");
      }
      out.println("</body>");
      out.println("</html>");
    }
  }
   public   void  doPost(HttpServletRequest request,
                    HttpServletResponse response)
     throws  IOException, ServletException {
    doGet(request, response);
  }
}

Вот фрагмент который вывполняется всеми сессиями (потоками)
последовательно.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
       synchronized  (links){
        Integer count = (Integer) links.get(link);
         if  (count ==  null ) {
          links.put(link,  new  Integer( 1 ));
        }
         else  {
          links.put(link,  new  Integer( 1 +count.intValue()));
        }
      }

А вот фрагмент, который выполняется параллельно.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
       if  (links.size() !=  0 ) {
        Enumeration enum = links.keys();
         while  (enum.hasMoreElements()) {
          String key = (String)enum.nextElement();
           int  count = ((Integer)links.get(key)).intValue();
          out.println(key+" : "+count+" visits<br>");
        }
      }

links - общий ресурс. Методы size и get скорее всего не вызывают криминала.
Однако, если бы эти методы в свою очередь обращались к общему ресурсу,
могла бы возникнуть неприятность. Вопрос, как читая подобный (чужой) код
можно идентифицировать методы, опасные с точки зрения многопоточности,
если в документации об это ничего не говориться, а приводится только
описание интерфейса?
...
Рейтинг: 0 / 0
13.04.2005, 10:56
    #33012599
NotGonnaGetUs
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
synchronized
Если какой-то код может быть вызван из разных потоков и это может привести к "повреждению" данных, то нужно позаботится о синхронизации.
Это не обязательно должна быть примитивная синхронизация ключевым словом sync*. Можно использовать read/write lock и т.п. паттерны.

В твой пример специфичный. В нём нет кода который удалял бы из links записи.
Если бы такой код был, то итерация по кеys могла бы привести к NullPointerException.

А так, самое страшное, что может случиться, в выводимом html значение
"out.println(key+" : "+count+" visits<br>");" может не соответствовать "истинному".
Т.е.
1 - начинается генерация html
2 - приходит реквест с "link", который ещё не обработан в цикле 1
3 - в цикле до него до ходит очередь и выводится значение отличное от того, что было в момент времени 1.

2а - приходит реквест с "link", который уже обработан в цикле 1
3а - в html будет то значение, что было в момент времени 1.
...
Рейтинг: 0 / 0
13.04.2005, 11:06
    #33012648
wessen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
synchronized
...Однако, если бы эти методы в свою очередь обращались к общему ресурсу,
могла бы возникнуть неприятность...
Эти методы и так обращаются к общему ресурсу (links), только криминала они не вызывают, потомучто они читают, а одновременно читать из общего кеша по идеи может не ограниченное число потоков. Вот если бы они одновременно писали в этот кеш....


Вопрос, как читая подобный (чужой) код
можно идентифицировать методы, опасные с точки зрения многопоточности,
если в документации об это ничего не говориться, а приводится только
описание интерфейса?

А никак. Т.е. можно, но только после того, как ты на эти грабли наступишь, получишь например ConcurrentModificationException или непонятно как и кем испорченные данные.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / synchronized / 3 сообщений из 3, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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