2015-12-27 2 views
3

У меня есть несколько потоков, обращающихся к class Aufzahlen и увеличивая переменную cc. Интересно, не помещаю ли я cc на volatile, но мой метод на синхронизированном есть ли место для ошибки здесь? Поскольку переменная cc будет доступна только один раз за раз.Неустойчивый, если метод синхронизирован?

Возможно ли, что потоки могут иметь переменную cc в своем кеше и для этого бесполезно? Некоторое время я запускал этот пример кода и до сих пор не обнаружил ошибок.

public class Aufzahlen { 
private int cc=1; 

    public synchronized void aufzahlen() throws InterruptedException { 
    cc = cc +1; 
    } 


    public synchronized void printa() { 
    // TODO Auto-generated method stub 
    System.out.println("Thread: " + Thread.currentThread() + "Zahl: " + cc); 
    } 

{ 
+0

Если вы правильно синхронизируете все другие обращения к 'cc', то нет, переменная не должна быть изменчивой. Как есть, переменная cc бесполезна, поскольку никто ее не читает.Не знаете, почему у вас есть 'throws InterruptedException'. Кроме того, вы можете использовать 'cC++'. –

+0

Я отредактировал метод для чтения переменной –

+0

Синхронизировать доступ к cc в порядке. Как уже упоминалось JB. Вы также можете использовать AtomicInteger, если заботиться только о cc. – Dwijendra

ответ

4

1. Видимость

Этот метод не подведет. При синхронизации каждый раз, когда вы доступ к полю, изменения к нему гарантированно будут видны каждый раз, когда нить имеет тот же замок, как показано ниже:

enter image description here

От Java Параллелизм В практике [pdf], Рисунок 3.1

Поэтому не обязательно, чтобы поле было изменчивым. Вероятно, вам намного лучше, используя методы AtomicIntegergetAndIncrement() и incrementAndGet(), которые работают с той же целью, но с лучшей пропускной способностью параллелизма (они используют встроенную функциональность вместо блокировки, они были разработаны именно для этой задачи), но убедитесь, что указана память в AtomicInteger (самый простой способ сделать это - сделать его окончательным - он не сделает значение AtomicInteger окончательным).

public class Aufzahlen { 
    private final AtomicInteger atomicInt = new AtomicInteger(1); // set initial value with constructor argument 

    public void aufzahlen() { 
     atomicInt.incrementAndGet(); 
    } // no need for synchronization because updates are atomic and are automatically visible 
} 

2. Атомарность

я мог бы использовать «атомный» один или два раза в этой должности, то это означает, что никакие два потока не могут быть одновременно выполняет один и тот же код, или, другими словами, что операция не может быть «разделена» на несколько частей, в которые одновременно могут входить несколько потоков.

+--- Function aufzählen() without synchronization and with i++ ---------------+ 
|                    | 
| [Get i from field] --> [Increment i locally] --> [Write new value to field] | 
|     ^      ^       | 
|      |       |        | 
|   "Race condition", multiple threads could be at these stages  | 
|   -> operation not atomic           | 
+-----------------------------------------------------------------------------+ 

Я просто demonstated, что не является атомарным, вы можете сделать эту операцию атомной с помощью synchronized (следующий потока должен ждать первый закончить весь метод), или вы можете использовать AtomicInteger, который делает эту атомарность для вы.

0

volatile переменных сказать компилятору никогда не кэшировать их значение в регистре в обеих операциях чтения и записи. Кэш-память CPU (L1, L2 и т. Д.) Все еще используется.

Если все обращения к этой переменной (в одном экземпляре класса) поступают из нескольких потоков, все они должны быть защищены.

Если вам интересно прочитать это значение cc из другого потока без синхронизации, тогда да, сделайте это volatile. Это позволит сделать синхронизацию блокировкой записи.

+0

Это утверждение верно? Простой ответ заключается в следующем: синхронизируются всегда может быть использован, чтобы дать вам потокобезопасный/правильное решение, летучие, вероятно, будет быстрее, но может быть использован только, чтобы дать вам потокобезопасного/правильно ограниченные ситуации. –

0

Нет проблем с исходным кодом из-за синхронизированного блока. Поле cc будет доступно только один поток одновременно, потому что два разных потока не смогут одновременно выполнять синхронизированный блок.

Смежные вопросы