Как синхронизировать статическую переменную среди потоков, выполняющих разные экземпляры класса в java?
Я знаю, что использование ключевого слова synchronize до того, как метод приносит синхронизацию с этим объектом.
То есть будут синхронизированы 2 потока, запускающих один и тот же экземпляр объекта.
Однако, поскольку синхронизация находится на уровне объекта, 2 потока, выполняющие разные экземпляры объекта, не будут синхронизированы. Итак, если у нас есть статическая переменная в классе java, которая вызывается методом, мы бы хотели, чтобы она была синхронизирована между экземплярами класса.
Два экземпляра работают в двух разных потоках.
Можем ли мы добиться синхронизации следующим образом?
public class Test
{
private static int count = 0;
private static final Object lock= new Object();
public synchronized void foo()
{
synchronized(lock)
{
count++;
}
}
}
Верно ли, что, поскольку мы определили объект "блокировка", который является статичным, и мы используем ключевое слово, синхронизированное для этой блокировки, статический счет varibale теперь синхронизируется между экземплярами класса Test?
Ответы
Ответ 1
Существует несколько способов синхронизации доступа к статической переменной.
-
Использовать синхронизированный статический метод. Это синхронизирует объект класса.
public class Test {
private static int count = 0;
public static synchronized void incrementCount() {
count++;
}
}
-
Явная синхронизация объекта класса.
public class Test {
private static int count = 0;
public void incrementCount() {
synchronized (Test.class) {
count++;
}
}
}
-
Синхронизировать другой статический объект.
public class Test {
private static int count = 0;
private static final Object countLock = new Object();
public void incrementCount() {
synchronized (countLock) {
count++;
}
}
}
Метод 3 является лучшим во многих случаях, поскольку объект блокировки не отображается вне вашего класса.
Ответ 2
Если вы просто используете счетчик, подумайте об использовании AtomicInteger или другого подходящего класса из пакета java.util.concurrent.atomic:
public class Test {
private final static AtomicInteger count = new AtomicInteger(0);
public void foo() {
count.incrementAndGet();
}
}
Ответ 3
Да, это правда.
Если вы создаете два экземпляра своего класса
Test t1 = new Test();
Test t2 = new Test();
Затем t1.foo и t2.foo синхронизируются на одном и том же статическом объекте и, следовательно, блокируют друг друга.
Ответ 4
Вы можете синхронизировать свой код над классом. Это было бы проще.
public class Test
{
private static int count = 0;
private static final Object lock= new Object();
public synchronized void foo()
{
synchronized(Test.class)
{
count++;
}
}
}
Надеюсь, вы найдете этот ответ полезным.
Ответ 5
Если это только одно целое, вы также можете использовать
Interlocked.Increment(count)
(пространство имен - System.Threading).