#java #multithreading #synchronization
#java #многопоточность #синхронизация
Вопрос:
У меня есть следующий код:
public class MyThread extends Thread {
private int i;
public static int sum=0;
public MyThread(int k){
i=k;
}
public static void main(String[] args) throws InterruptedException{
Thread t=new MyThread(1);
Thread s=new MyThread(2);
Thread p=new MyThread(3);
t.start();
s.start();
}
public synchronized void doSomething(){
for(int i=0; i<100000; i ){
System.out.println(this.i);
}
}
@Override
public void run() {
doSomething();
}
}
doSomething синхронизирован. почему вывод случайный?
Я предполагаю, что синхронизированный метод будет таким же, как синхронизированный блок, но вывод блока — sync, а метод — нет.
Комментарии:
1. Что вы подразумеваете под «случайным»? Из кода видно, что у вас запущено 3 потока, каждому будет выделено процессорное время, и поэтому выходные данные будут чередоваться.
Ответ №1:
synchronized
Ключевое слово там предотвращает чередование синхронизированных вызовов методов для одного и того же объекта. Это не предотвращает чередование вызовов методов для разных объектов. Поскольку у вас есть три разных объекта, три вызова могут выполняться одновременно.
Вам необходимо выполнить синхронизацию на одном объекте, который является общим для всех трех потоков.
Ответ №2:
Синхронизация методов выполняется только для вызовов одного и того же объекта. Вы создаете два разных объекта (два потока).
Ответ №3:
Блокировка, используемая synchronized
методами, связана с экземпляром класса MyThread
. Поскольку каждый поток имеет свой собственный экземпляр MyThread
, каждый поток синхронизируется по своей собственной блокировке.
Если вы хотите синхронизировать все потоки, вы могли бы сделать что-то вроде:
public class MyThread extends Thread {
private static final Object sharedLock = new Object();
public void doSomething() {
synchronized(sharedLock) {
for(int i=0; i<100000; i ) {
System.out.println(this.i);
}
}
}
...
}
Альтернативой является synchronize
on MyThread.class
, но я предпочитаю первый подход.
В комментариях вы говорите, что если вы измените свой код на использование synchronized(this)
в doSomething
, внезапно это сработает. Я почти уверен, что это не так. Возможно, это сработало случайно, но оно не будет работать постоянно и надежно.
Комментарии:
1. но если я изменю его на synchronized (this) и помещу цикл внутрь, он действительно получит упорядоченные результаты, но синхронизация выполняется в экземпляре класса mythread