Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/4: Рейтинг темы: голосов - 4, средняя оценка - 4.50
39 / 26 / 18
Регистрация: 30.09.2014
Сообщений: 142

Снова многопоточность: совместный доступ к объекту

30.03.2017, 19:51. Показов 779. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. Начал самостоятельно изучать Java. Дойдя до вопросов многопоточности, решил написать тестовую программу, в которой класс MyNumber (оболочка для int), IncThread - класс, реализующий интерфейс Runnable и Main - общий. Суть программы состоит в том, что объект класса MyNumber передается в два объекта IncThread и в каждом из них число объекта MyNumber инкрементируется, причем в первом на 1, а во втором - на 2. Выглядит это все так:
Java
1
2
3
4
5
6
7
8
9
10
package testproj;
 
public class MyNumber
{
    public int number;
    MyNumber(int i)
    {
        number = i;
    }
}
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
package testproj;
 
public class IncThread implements Runnable
{
    Thread t;
    String name;
    public MyNumber num;
    int i;
    IncThread(MyNumber n, int in, String nm)
    {
        num = n;
        i = in;
        name = nm;
        t = new Thread(this);
        t.start();
    }
    @Override
    public void run()  
    {
        while(true)
        {
            incr();             
        }
        
    }
    void incr()
    {
        synchronized(num)
        {
            try
            {
                Thread.sleep((int)(500+Math.random()*500));
                //Thread.sleep(1000);
                num.number+=i;
                System.out.println(name+": "+num.number+" ");
            }
            catch (InterruptedException e)
            {
            
            }
        }
    }
    
 
}
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package testproj;
 
 
public class Main
{
 
    public static void main(String[] args)
    {
        MyNumber n = new MyNumber(0);
        IncThread inct1 = new IncThread(n,1,"Thread 1");
        IncThread inct2 = new IncThread(n,2,"Thread 2");
    }
 
}
Вывод программы такой:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Thread 1: 1 
Thread 1: 2 
Thread 1: 3 
Thread 1: 4 
Thread 1: 5 
Thread 1: 6 
Thread 1: 7 
Thread 1: 8 
Thread 2: 10 
Thread 2: 12 
Thread 2: 14 
Thread 2: 16 
Thread 2: 18 
Thread 2: 20 
Thread 2: 22 
Thread 2: 24 
Thread 2: 26 
Thread 2: 28
То есть, почему-то сначала выполняется какое-то количество итераций первого потока, потом второго, потом снова первого и т.д. Видимо, это связано с применением synchronized-блока в методе incr(). Но ведь, насколько я понимаю, если его не применить, правильный вывод числа не гарантируется? В принципе, я пробовал его убирать, и в таком случае время от времени оба потока одновременно выводят одно и то же число (то есть, один поток успевает изменить его до того, как второй его выводит после своего инкремента). Правильно ли я применяю synchronized-блок, или есть какой-то более правильный способ запретить вхождение в монитор объекта MyNumber, если он уже занят?
Пробовал также создавать синхронизированный метод в классе MyNumber:
Java
1
2
3
4
    synchronized void inc(int k)
    {
        number+=k;
    }
И вызывать его в потоке:
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
    public void run()  
    {
        while(true)
        {
            incr();             
        }
        
    }
    void incr()
    {
        //synchronized(num)
        {
            try
            {
                Thread.sleep((int)(500+Math.random()*500));
                //Thread.sleep(1000);
                //num.number+=i;
                num.inc(i);
                System.out.println(name+": "+num.number+" ");
            }
            catch (InterruptedException e)
            {
            
            }
        }
    }
И тогда все работает нормально. Но в чем принципиальная разница в этих двух подходах? Ведь и там и там код инкремента синхронизируется по объекту типа MyNumber
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
30.03.2017, 19:51
Ответы с готовыми решениями:

Совместный доступ к объекту из разных форм
Такой вопросик. Есть несколько форм в проекте. Есть так же экземпляр определённого класса. Нужно сделать так, чтобы все формы видели этот...

Совместный доступ к бд
Всем доброго времени суток. Столкнулся с проблемой при написании диплома. Суть задачи такая: Есть WinService который опрашивает датчик...

Совместный доступ к файлам
Ребят,помогите пожалуйста с задачкой.Нужно написать код на php на совместный доступ к файлам.

4
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,779
30.03.2017, 21:27
Ты очень рано взялся за многопоточность. И зря взял книгу Шилдта.
0
39 / 26 / 18
Регистрация: 30.09.2014
Сообщений: 142
30.03.2017, 21:48  [ТС]
korvin_, допустим. Но что конкретно неправильно?
0
$ su
 Аватар для ntlinuxnt
1605 / 520 / 97
Регистрация: 18.11.2010
Сообщений: 2,807
Записей в блоге: 2
01.04.2017, 15:28
Конкретно то что, изменять одно и тоже из двух разных потоков это не есть хорошо.
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,779
01.04.2017, 17:17
Цитата Сообщение от artem2302 Посмотреть сообщение
Но что конкретно неправильно?
Да очень много что.

Цитата Сообщение от artem2302 Посмотреть сообщение
Java
1
public int number;
не потокобезопасно.

Цитата Сообщение от artem2302 Посмотреть сообщение
Java
1
public class IncThread implements Runnable
Зачем называть класс *Thread, если он не Thread? Ну это так, замечание.

Цитата Сообщение от artem2302 Посмотреть сообщение
Java
1
2
3
4
Thread t;
...
        t = new Thread(this);
* * * * t.start();
Создавать и запускать Thread в конструкторе Runnable — это надо быть сильным извращенцем. Runnable используется не так. Ещё и утечка this в конструкторе. http://www.javapractices.com/t... .do?Id=252

Цитата Сообщение от artem2302 Посмотреть сообщение
Java
1
2
3
4
5
6
7
8
9
    public MyNumber num;
    ...
    IncThread(MyNumber n, int in, String nm)
    {
        num = n;
    ...
    void incr()
    {
        synchronized(num)
Стоит кому-нибудь извне залочить n и твой IncThread просто зависнет.

Java
1
2
3
4
            catch (InterruptedException e)
            {
            
            }
https://www.ibm.com/developerw... -jtp05236/
Sometimes throwing InterruptedException is not an option, such as when a task defined by Runnable calls an interruptible method. In this case, you can't rethrow InterruptedException, but you also do not want to do nothing. When a blocking method detects interruption and throws InterruptedException, it clears the interrupted status. If you catch InterruptedException but cannot rethrow it, you should preserve evidence that the interruption occurred so that code higher up on the call stack can learn of the interruption and respond to it if it wants to. This task is accomplished by calling interrupt() to "reinterrupt" the current thread, as shown in Listing 3. At the very least, whenever you catch InterruptedException and don't rethrow it, reinterrupt the current thread before returning.
Цитата Сообщение от artem2302 Посмотреть сообщение
То есть, почему-то сначала выполняется какое-то количество итераций первого потока, потом второго, потом снова первого и т.д.
Почему-то? Ты хоть какую-нибудь теорию почитай.

Цитата Сообщение от artem2302 Посмотреть сообщение
Правильно ли я применяю synchronized-блок
Неправильно.

Цитата Сообщение от artem2302 Посмотреть сообщение
есть какой-то более правильный способ
Есть.

Матчасть подучи.

Цитата Сообщение от artem2302 Посмотреть сообщение
Пробовал также создавать синхронизированный метод в классе MyNumber
А если и дальше продолжешь использовать «метод тыка», то потратишь кучу времени и так и продолжишь топтаться на одном месте.

Цитата Сообщение от artem2302 Посмотреть сообщение
Но в чем принципиальная разница в этих двух подходах? Ведь и там и там код инкремента синхронизируется по объекту типа MyNumber
В том, что синхронизируются они в разных участках кода.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.04.2017, 17:17
Помогаю со студенческими работами здесь

Совместный доступ к памяти
Надо сделать имитатор 2-х портовой памяти. Есть 2 программы: одна с частотой 100 Гц. записывает массив в память, а другая с той же частотой...

Совместный доступ к базе
Доброго времени суток! Интересует совместный доступ к БД Access, а именно: Одновременно работает 2 человека: Первый человек изменяет...

Совместный доступ к файлам
Ребят помогите пожалуйста с задачкой по С# ....нужно создать совместный доступ к файлам....если можете напишите код))

Макрос и совместный доступ
наверное много на эту тему уже писали, но ответа на свой вопрос я не нашла при включении совместного доступа макрос просто не запускается...

Совместный доступ к Access
Уважаемые знатоки, подскажите как лучше организовать работу нескольких пользователей с базой данных Access. У меня есть формы...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru