синхронизация по блоку кода - PullRequest
0 голосов
/ 25 февраля 2011

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

когда мы пишем класс потока в методе запуска, который мы запускаемсинхронизированный блок, давая объект.например,

 class MyThread extends Thread{
   String sa;
   public MyThread(String s){
       sa=s;
   } 
   public void run(){
     synchronized(sa){
         if(sa.equals("notdone"){
             //do some thing on object
         }
     }
   }    
 }

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

Ответы [ 4 ]

1 голос
/ 25 февраля 2011

Я бы предложил

  • расширение Runnable, а не Thread.
  • не блокируйте Runnable на внешнем. Вместо этого вы должны вызывать метод, который может использовать внутреннюю блокировку.
  • Строка не подходит для блокировки. Это означает, что "hi" и "hi" будут совместно использовать блокировку, но новая строка ("hi") не будет.
  • если вы блокируете все другие потоки на весь срок службы потока, почему вы используете несколько потоков?
1 голос
/ 25 февраля 2011

Объект параметра синхронизированного блока - это объект, на который блокируется блок.Таким образом, все синхронизированные блоки с одним и тем же объектом исключают одновременное выполнение друг друга (и всех синхронизированных методов этого же объекта).

Так что, если у вас есть этот пример

class ExampleA extends Thread() {

    public ExampleA(Object l) {
       this.x = l;
    }

    private Object x;

    public void run() {
        synchronized(x) {     // <-- synchronized-block A
            // do something
        }
    }
}
class ExampleB extends Thread() {

    public ExampleB(Object l) {
       this.x = l;
    }

    private Object x;

    public void run() {
        synchronized(x) {     // <-- synchronized-block B
            // do something else
        }
    }
}

Object o1 = new Object();
Object o2 = new Object();

Thread eA1 = new ExampleA(o1);
Thread eA2 = new ExampleA(o2);
Thread eB1 = new ExampleB(o1);
Thread eB2 = new ExampleB(o2);

eA1.start(); eA2.start(); eB1.start(); eB2.start();

Теперь у нас есть два синхронизированных блока (A и B, в классах ExampleA и ExampleB), и у нас есть два объекта блокировки (o1 и o2).

Еслитеперь мы посмотрим на одновременное выполнение, мы можем видеть, что:

  • A1 может выполняться параллельно с A2 и B2, но не с B1.
  • A2 может выполняться параллельнодля A1 и B1, но не для B2.
  • B1 может выполняться параллельно с A2 и B2, но не для A1.
  • B2 может выполняться параллельно с A1 и B1, ноне в A2.

Таким образом, синхронизация зависит только от объекта параметра , а не от выбора блока синхронизации.


В вашем примере, вы используете это:

 synchronized(sa){
     if(sa.equals("notdone"){
         //do some thing on object
     }
 }

Похоже, вы пытаетесь избежать того, чтобы кто-то изменил вашпеременная позиции sa в другую строку, когда вы сравниваете ее и работаете - но это не избегает этого.

Синхронизация не работает с переменной , она работает с объектом - ирассматриваемый объект обычно должен быть каким-либо объектом, который содержит переменную (текущий MyThread объект в вашем случае, достижимый this), или специальным объектом, используемым только для синхронизации, и который не изменяется.

Как сказал Питер Лоури, строковые объекты обычно являются плохим выбором для блокировок синхронизации, поскольку все равные литералы String являются одним и тем же объектом (то есть исключают синхронизированные блоки друг друга), в то время как одинаковые не-литеральные строки (например, созданные во время выполнения)не является тем же объектом, и, следовательно, не исключает синхронизированные блоки другими такими объектами или литералами, что часто приводит к незначительным ошибкам.

0 голосов
/ 26 февраля 2011

Итак, вопрос в том, какова функция объекта, на котором синхронизируется блок?

Все экземпляры Объект имеют так называемый монитор . В обычном исполнении этот монитор неизвестен.

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

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

0 голосов
/ 25 февраля 2011

Все потоки, синхронизированные на этом объекте, будут ждать, пока текущий поток завершит свою работу. Это полезно, например, если у вас есть операция чтения / записи в коллекцию, которую вы хотите синхронизировать. Таким образом, вы можете написать синхронизированный блок в методах set и get. В этом случае, если один поток читает информацию, не все другие потоки, которые хотят либо читать, либо писать, будут ждать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...