Давно пишу на java, но треды и синхронизацию использовал очень редко, отсюда появилась одна проблема. Наткнулся на вопрос из Java2 BrainBench — Имеется следующий код и варианты ответов
----------------------------------------------------------------------------
public class ThreadUnsafe {
private static int commonCounter=0;
public int getCount() {return commonCounter;}
public void addCount(int val) { commonCounter+=val;}
public void subtractCount(int val)
{ commonCounter-=val; }
}
Which one of the following changes makes the class defined above thread-safe?
Choice 1
Wrap the ThreadUnsafe object within a class that declares all methods as synchronized.
Choice 2
Modify getCount(), addCount(), and subtractCount() to synchronize on a static object instance.
Choice 3
Have ThreadUnsafe implement the java.servlet.SingleThreadModel interface.
Choice 4
Store the ThreadUnsafe objects in a collection created using Collections.synchronizedCollection().
Choice 5
Change the definition of commonCounter to "protected static int."
----------------------------------------------------------------------------
Подумав, что правильный ответ — это Choice 2 попробовал написать простенький тестовый пример. Вот что получилось:
public class App1 {
public static void main(String args[]) {
Class1 t1 = new Class1("Thread_1");
Class1 t2 = new Class1("Thread_2");
t1.start();
t2.start();
}
}
public class Class1 extends Thread {
public Class1 (String name) {
super(name);
}
private static int commonCounter = 0;
private long i = 0;
public void run() {
while (true) {
i++;
if (i % 10000000 == 0) System.out.println(this.getName()+" "+i);
synchronized (this) {
commonCounter++;
--commonCounter;
if (commonCounter!=0) System.out.println(commonCounter+"!=0");
}
}
}
}
Оказалось что результат выполнения программы выглядит не так как ожидалось:
....
1!=0
1!=0
1!=0
1!=0
Thread_1 20000000
Thread_2 20000000
1!=0
1!=0
....
....
То есть не смотря на то, что статический счетчик инкрементируется и тут же декрементируется в synchronized блоке два треда все равно используют этот блок одновременно!
Понимаю, что что-то здесь не так. Но что? Может кто подскажет...