2017-01-02 2 views
2

Я просто учусь на экзамен, и у меня есть следующие ноны поточно-код из предыдущего вопроса экзамена:сделать этот класс потокобезопасные

class Q3 { 
    private boolean f[] = new boolean[20]; 

    public Q3() { 
     for (int j = 0; j < 20; j++) { 
      f[j] = true; 
     } 
    } 

    public void negate(int a, int b) { 
     for(int j = a; j < b; j++) { 
      f[j] = !f[j]; 
     } 
    } 

    public void swap(int a, int b) { 
     boolean temp = f[a]; 
     f[a] = f[b]; 
     f[b] = temp; 
    } 
} 

Я сделал это поточно, сделав следующие настройки:

class Q3 { 
    private boolean f[] = new boolean[20]; 

    public Q3() { 
     for (int j = 0; j < 20; j++) { 
      f[j] = true; 
     } 
    } 

    synchronized void negate(int a, int b) { 
     for (int j = a; j < b; j++) { 
      f[j] = !f[j]; 
     } 
    } 

    synchronized void swap(int a, int b) { 
     boolean temp = f[a]; 
     f[a] = f[b]; 
     f[b] = temp; 
    } 
} 

Но может ли кто-нибудь объяснить мне, почему исходный код не является потокобезопасным? Я знаю, как сделать безопасный поток кода, если это не так, но я все еще не уверен, почему код не определен как потокобезопасный.

+0

Можете ли вы показать нам, как используется класс 'Q3'? –

+0

Это не используется в любом контексте, вопрос просто просит сделать поток кода безопасным, что я и сделал, мне просто интересно, почему он не был потокобезопасным, в первую очередь, который не был частью вопрос, но я хотел бы знать, как отличить код, который является или не является потокобезопасным. –

+0

Вы, jsut, удалили свой последний вопрос, когда я отправлял решение @ JohnP.Lally. 'android: minSdkVersion =" 10 "' должно быть ''. Ваша сборка должна быть неудачной. –

ответ

1

Скажем, 2 потока одновременно вызывают отрицание и своп соответственно, и все индексы имеют значение true изначально. Теперь давайте скажем, что оба потока одновременно считывают значение = true в 4-м индексе. 1-й поток вызывает отрицание и его отрицание 4-го элемента делает его ложным, в то же время 2-й поток читает 4-й элемент и свопит к 5-му элементу, который является истинным. Таким образом, конечным результатом в этом случае будет 4-е значение индекса = false 5-е значение индекса = true.

Теперь, поскольку мы не можем предсказать порядок выполнения, это может быть другой сценарий выполнения. Нить 1 читает 4-й элемент, делает его ложным, а затем поток 2 считывает значение после обновления 1-го потока, поэтому читает его как false и заменяет это значение на 5-й элемент. Таким образом, в этом случае конечным результатом будет значение 4-го индекса = true и 5-й индекс = false Итак, в нижней строке, если мы не будем синхронизировать, мы не можем предсказать порядок выполнения потока и получить неожиданный результат. Таким образом, когда вы говорите, что синхронизированы, эти 2 метода никогда не будут вызываться вместе, и, следовательно, невозможно одновременно считывать и записывать один и тот же элемент индекса несколькими потоками.

2

Этот ответ предполагает, что несколько потоков могут воздействовать на один и тот же экземпляр объекта Q3. Принимая метод swap() в качестве примера:

public void swap(int a, int b) { 
    boolean temp = f[a]; 
    f[a] = f[b]; 
    f[b] = temp; 
} 

Если две отдельные нити были как вызов swap() и чередовании, следующий может произойти:

Thread one: 
boolean temp = f[a]; 
f[a] = f[b]; 

Thread two: 
boolean temp = f[a]; // his temp = f[b], wrong! 

Thread one: 
f[b] = temp;   // f[b] = f[b], no swap! 

Thread two: 
f[a] = f[b]; 
f[b] = temp;   // f[a] = f[b], wrong 

Конечным результатом этого является то, что как f[a] и f[b] в конечном итоге со значением последнего, для и тем, что явно не то, что вы хотите. Выбрав метод swap() 10, вы убедитесь, что данный поток выполнит этот метод атомарно, то есть данный поток будет либо полностью закончить весь метод, либо не будет иметь ничего между ними.

+0

Ну ладно, думаю, я понимаю, что вы сейчас говорите, спасибо! –

+0

@ JohnP.Lally Возможно ли повышение? –

+0

Я пытался, но потому, что у меня репутация менее 15, это не позволит мне –

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